Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do linkers decide what parts of libraries to include?

Tags:

c

linker

Assume library A has a() and b(). If I link my program B with A and call a(), does b() get included in the binary? Does the compiler see if any function in the program call b() (perhaps a() calls b() or another lib calls b())? If so, how does the compiler get this information? If not, isn't this a big waste of final compile size if I'm linking to a big library but only using a minor feature?

like image 717
Oliver Zheng Avatar asked Apr 03 '09 20:04

Oliver Zheng


People also ask

Where does the linker look for libraries?

By default, the runtime linker knows of only one standard place to look for libraries, /usr/lib when processing 32-bit objects, and /usr/lib/64 when processing 64-bit objects. All other directories to be searched must be added to the runtime linker's search path explicitly.

How does the linker work?

In computing, a linker or link editor is a computer system program that takes one or more object files (generated by a compiler or an assembler) and combines them into a single executable file, library file, or another "object" file.

How linkers are used during the compilation process?

The linker is what produces the final compilation output from the object files the compiler produced. This output can be either a shared (or dynamic) library (and while the name is similar, they haven't got much in common with static libraries mentioned earlier) or an executable.

What is the task of a linker What are the other functions of it?

Three functions of a linker: Combine all the pieces of a program. Figure out a new memory organization so that all the pieces fit together (combine like sections). Touch up addresses so that the program can run under the new memory organization.


4 Answers

Take a look at link-time optimization. This is necessarily vendor dependent. It will also depend how you build your binaries. MS compilers (2005 onwards at least) provide something called Function Level Linking -- which is another way of stripping symbols you don't need. This post explains how the same can be achieved with GCC (this is old, GCC must've moved on but the content is relevant to your question).

Also take a look at the LLVM implementation (and the examples section).

I suggest you also take a look at Linkers and Loaders by John Levine -- an excellent read.

like image 97
dirkgently Avatar answered Dec 26 '22 20:12

dirkgently


It depends.

If the library is a shared object or DLL, then everything in the library is loaded, but at run time. The cost in extra memory is (hopefully) offset by sharing the library (really, the code pages) between all the processes in memory that use that library. This is a big win for something like libc.so, less so for myreallyobscurelibrary.so. But you probably aren't asking about shared objects, really.

Static libraries are a simply a collection of individual object files, each the result of a separate compilation (or assembly), and possibly not even written in the same source language. Each object file has a number of exported symbols, and almost always a number of imported symbols.

The linker's job is to create a finished executable that has no remaining undefined imported symbols. (I'm lying, of course, if dynamic linking is allowed, but bear with me.) To do that, it starts with the modules named explicitly on the link command line (and possibly implicitly in its configuration) and assumes that any module named explicitly must be part of the finished executable. It then attempts to find definitions for all of the undefined symbols.

Usually, the named object modules expect to get symbols from some library such as libc.a.

In your example, you have a single module that calls the function a(), which will result in the linker looking for module that exports a().

You say that the library named A (on unix, probably libA.a) offers a() and b(), but you don't specify how. You implied that a() and b() do not call each other, which I will assume.

If libA.a was built from a.o and b.o where each defines the corresponding single function, then the linker will include a.o and ignore b.o.

However, if libA.a included ab.o that defined both a() and b() then it will include ab.o in the link, satisfying the need for a(), and including the unused function b().

As others have mentioned, there are linkers that are capable of splitting individual functions out of modules, and including only those that are actually used. In many cases, that is a safe thing to do. But it is usually safest to assume that your linker does not do that unless you have specific documentation.

Something else to be aware of is that most linkers make as few passes as they can through the files and libraries that are named on the command line, and build up their symbol table as they go. As a practical matter, this means that it is good practice to always specify libraries after all of the object modules on the link command line.

like image 21
RBerteig Avatar answered Dec 26 '22 19:12

RBerteig


It depends on the linker.

eg. Microsoft Visual C++ has an option "Enable function level linking" so you can enable it manually.

(I assume they have a reason for not just enabling it all the time...maybe linking is slower or something)

like image 38
Jimmy J Avatar answered Dec 26 '22 19:12

Jimmy J


Usually (static) libraries are composed of objects created from source files. What linkers usually do is include the object if a function that is provided by that object is referenced. if your source file only contains one function than only that function will be brought in by the linker. There are more sophisticated linkers out there but most C based linkers still work like outlined. There are tools available that split C source that contain multiple functions into artificially smaller source files to make static linking more fine granular.

If you are using shared libraries then you don't impact you compiled size by using more or less of them. However your runtime size will include them.

like image 45
lothar Avatar answered Dec 26 '22 19:12

lothar