5

I asked myself the following question, when I was discussing this topic .

Are there cases when some unused code from translation units will link to final executable code (in release mode of course) for popular compilers like GCC and VC++?

For example suppose we have 2 compilation units:

//A.hpp
//Here are declarations of some classes, functions, extern variables etc.

And source file

//A.cpp
//defination of A.hpp declarations

And finally main

//main.cpp
//including A.hpp library
#include "A.hpp"
//here we will use some stuff from A.hpp library, but not everything

My question is. What if in main.cpp not all the stuff from A.hpp is used? Will the linker remove all unused code, or there are some cases, when some unused code can link with executable file?

Edit: I'm interested in G++ and VC++ linkers.

Edit: Of course I mean in release mode.

Edit: I'm starting bounty for this question to get good and full answer. I'm expecting answer, which will explain in which cases g++ and VC++ linkers are linking junk and what kind of code they are able to remove from executable file(unneeded functions, unneeded global variables, unneeded class definitions, etc...) and why aren't they able to remove some kind of unneeded stuff.

Community
  • 1
  • 1
UmmaGumma
  • 5,633
  • 1
  • 31
  • 45
  • 1
    Specify compiler please. – leppie Jan 27 '11 at 10:37
  • For GCC, search SO for `-gc-sections`. I have previously answered that question. I think it is called Function-level linking for VC++. – leppie Jan 27 '11 at 11:24
  • @leppie I searched in internet for Function level linking. Ok, It's partially answer, but what about classes, external variables etc.. ? Will they remove from executable file too, or not? And also Is there something like that for gcc? – UmmaGumma Jan 27 '11 at 11:38
  • http://stackoverflow.com/questions/4274804/query-on-ffunction-section-fdata-sections-options-of-gcc – leppie Jan 27 '11 at 11:48

4 Answers4

5

As other posters have indicated, the linker typically does not remove dead code before building the final executable. However, there are often Optimization settings you can use to force the linker to try extra hard to do this.

For GCC, this is accomplished in two stages:

  1. First compile the data but tell the compiler to separate the code into separate sections within the translation unit. This will be done for functions, classes, and external variables by using the following two compiler flags:

    -fdata-sections -ffunction-sections

  2. Link the translation units together using the linker optimization flag (this causes the linker to discard unreferenced sections):

    -Wl,--gc-sections

So if you had one file called test.cpp that had two functions declared in it, but one of them was unused, you could omit the unused one with the following command to gcc(g++):

gcc -Os -fdata-sections -ffunction-sections test.cpp -o test.o -Wl,--gc-sections

(Note that -Os is an additional linker flag that tells GCC to optimize for size)

I have also read somewhere that linking static libraries is different though. That GCC automatically omits unused symbols in this case. Perhaps another poster can confirm/disprove this.

As for MSVC, as others have mentioned, function level linking accomplishes the same thing. I believe the compiler flag for this is (to sort things into sections):

/Gy

And then the linker flag (to discard unused sections):

/OPT:REF

EDIT: After further research, I think that bit about GCC automatically doing this for static libraries is false.

J T
  • 4,946
  • 5
  • 28
  • 38
1

The linker will not remove code.

You can still access it via dlsym dynamically in your code.

Benoit Thiery
  • 6,325
  • 4
  • 22
  • 28
  • 2
    Well of course you can tell the linker to discard unused sections of code. – leppie Jan 27 '11 at 11:25
  • @Benoit Thiery I'm trying figure out how dlsym is working. I wrote fallowing program http://pastebin.com/YpfFTkkn and then try to call it's method from other one http://pastebin.com/en8NjsQF. But I'm getting segmenation fault. So what I'm doing wrong? – UmmaGumma Jan 27 '11 at 12:15
  • dlopen allows to load a dynamic library (.so file), but not another executable. Please check errors of dlopen before calling dlsym using the handle. – Benoit Thiery Jan 27 '11 at 12:22
  • @Benoit Thiery I'm asking will unneeded code present in EXECUTABLE file. If dlopen can't load executable files, than your answer isn't correct. – UmmaGumma Jan 27 '11 at 12:37
  • @Ashot Do not confuse dlopen and dlsym. dlsym can look symbols already present in your executable. – Benoit Thiery Jan 27 '11 at 12:46
  • @Benoit Thiery But how can I use dlsym without opening file? – UmmaGumma Jan 27 '11 at 15:44
1

In general, linkers tend to include everything from the object files explicitly passed on the command line, but only pull in those object files from a static library that contain symbols needed to resolve external references from object files already linked.

However, a linker may decide to discard functions that are never called, or data which is never referenced. The precise details will depend on the compiler and linker switches.

In C++ code, if a source file is explicitly compiled and linked in to your application then I would expect that the objects with static storage duration that have constructors and/or destructors will be included, and their constructors/destructors run at the appropriate times. Consequently, any code called from those constructors or destructors must be in the final executable. However, if the code is not called from anywhere then you cannot write a program to tell whether or not the code is included without using things like dlsym, so the linker may well omit to include it in the final executable.

I would also expect that any symbols defined with global visibility such that they could be found via dlsym (as opposed to "hidden" symbols which are only visible within the executable) would be present in the final executable. However, this is an expectation rather than something I have confirmed by testing or reading the docs.

Anthony Williams
  • 66,628
  • 14
  • 133
  • 155
0

If you wanted to ensure code was in your executable even if it isn't called by inside it, you could load it in as a statically aware dynamic link library (a statically aware library is one which is loaded automatically into memory as the program is loaded, as opposed to the functionality where you can pass a string to a function that loads a library and then you manually search for hooks)

deek0146
  • 962
  • 6
  • 20