Skip to content
Search

Ld

lastmod 2025-01-22created 2014-09-2580 edits

The GNU linker (or GNU ld) is the GNU Project's implementation of the Unix command ld. GNU ld runs the linker, which creates an executable file (or library) from the object files generated during compilation of software. A linker script can be passed to GNU ld to exercise greater control over the linking process. The GNU linker is part of the GNU Binary Utilities (binutils).

The suggested origins of the name "ld" include "LoaD" and "Link eDitor".

The GNU linker is free software and is distributed under the GNU General Public License.

Category

GNU Linker

BSD Linker

Used on Mac OSX and others. In GCC, see the Darwin Options. 1

Flags

-headerpad {size}
Specifies the minimum space for future expansion of the load commands. Only useful if intend to run install_name_tool to alter the load commands later. Size is a hexadecimal number.
-headerpad_max_install_names
Automatically adds space for future expansion of load commands such that all paths could expand to MAXPATHLEN. Only useful if intend to run install_name_tool to alter the load commands later.
Since the executable's header information may be changed by install_name_tool and the like, this reserves the maximum space defined by MAXPATHLEN. (Needs verification)
-compatibility_version {number}
Specifies the compatibility version number of the library. When a library is loaded by dyld, the compatibility version is checked and if the program's version is greater that the library's version, it is an error. The format of number is X[.Y[.Z]] where X must be a positive non-zero number less than or equal to 65535, and .Y and .Z are optional and if present must be non-negative numbers less than or equal to 255. If the compatibility version number is not specified, it has a value of 0 and no checking is done when the library is used. This option is also called -dylib_compatibility_ver-sion for compatibility.
Specifies the compatibility version number of the library. The format of {number} is X[.Y[.Z]], with the following constraints on the values.
0 < X <= 65535
[Optional] 0 <= .Y <= 255
[Optional] 0 <= .Z <= 255
-current_version {number}
Specifies the current version number of the library.
Specifies the current version of the library.
-search_paths_first
This is now the default (in Xcode4 tools). When processing -lx the linker now searches each directory in its library search paths for libx.dylib' thenlibx.a' before the moving on to the next path in the library search path.

About the sections of the ld program

When working on bootloaders or other firmware, you end up manipulating ld scripts. People usually copy and reuse them, but with a little understanding they are easy to modify.

  • .text: code area.
  • .bss: area for variables that exist outside functions and have no initial value. Even variables initialized to 0 are not included in the bss area.
  • .data: area for variables that exist outside functions and have an initial value. Variables initialized to 0 are also included here.
  • .rodata: read-only variables, variables declared const.
  • .got: Global Offset Table, start addresses related to shared libraries.

LD_LIBRARY_PATH vs LIBRARY_PATH

Two-line summary:

  • LD_LIBRARY_PATH - searched when the program starts,
  • LIBRARY_PATH - searched at link time.

For reference:

  • DYLD_LIBRARY_PATH - the macOS version of LIBRARY_PATH.
  • DYLD_FALLBACK_LIBRARY_PATH - paths to search if a library is not found in DYLD_LIBRARY_PATH above.

See #rpath below for details.

An example related to link order follows.

main.c:

#include <temp.h>
int main()
{
    return temp();
}

temp.h:

int temp();

temp.c:

#include <stdio.h>
int temp()
{
    printf("Hello, World!\n");
    return 0;
}

Assume each was built as an archive.

$ ar cr main.a main.o
$ ar cr temp.a temp.o

Linking as below then produces an error.

$ gcc temp.a main.a
main.a(main.o):main.c:(.text+0xe): undefined reference to `temp'
collect2.exe: error: ld returned 1 exit status

You must swap the order as below. Linking as below then produces an error.

$ gcc main.a temp.a

In short, link in the order {referencing library} -> {implementing library}.

If you don't want to worry about the order, use --start-group and --end-group.

How does ld.so find shared libraries?

  • By default it looks in /lib or /use/lib. It also looks in the paths specified in /etc/ld.so.conf, and searches the paths specified in LD_LIBRARY_PATH set up for each account.
  • For newly added libraries, add the relevant path under the /etc/ld.so.conf.d directory. 2
  • Caveat: it looks in the paths specified in /etc/ld.so.conf, so when you change its contents or upgrade or install system libraries, you must run the ldconfig command to generate /etc/ld.so/chche, the shared library cache that ld.so uses when searching paths.

Checking the library load order

Set the LD_DEBUG environment variable to files and run the file you want.

$ LD_DEBUG=files /bin/ls

Linker search path list

Use any one of the following methods.

ldconfig -v 2>/dev/null | grep -v ^$'\t'
ld --verbose | grep SEARCH_DIR | tr -s ' ;' \\012
gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,;  ,g' | tr \; \\012
gcc -Xlinker -v
gcc -Xlinker --verbose
gcc --print-search-dirs

List of found libraries

Use any one of the following methods.

ldconfig -v
ldconfig -p

soname

In Unix operating systems, soname is a field within a shared object file. The soname provides the system with backward version compatibility information. In short, if a program requests version 1.0 of a shared object but the system only has version 2.0, the system can look at the soname field in the shared object to determine whether it can use version 2.0 instead of version 1.0.

How to use

GCC Version:

$ gcc -shared -Wl,-soname,libtest.so.1.0 test.o

clang Version:

$ clang -dynamiclib test.o -o libtest.1.0.dylib -install_name,libtest.1.0.dylib -current_version 1.0.6 -compatibility_version 1.0

rpath

rpath is a term in programming which refers to a run-time search path hard-coded in an executable file or library, used during dynamic linking to find the libraries the executable or library requires.

In a word, it is a real-time library search path. The Linux dynamic linker uses these paths to find the required shared objects. It is also called RUNPATH.

You can check it with tools such as readelf on Linux systems and otool on darwin systems.

How to use

You can check or modify it with methods like the following.

$ objdump -x {file} | grep RPATH
$ readelf -d {file} | head -20
$ otool -D {file} ## to view the install name of a dylib
$ otool -L {file} ## to view the dependencies (<code>@rpath</code>가 붙는다.)
$ otool -l {file} | grep LC_RPATH -A2 ## to view the RPATHs
$ install_name_tool -id ... ## to change an install name
$ install_name_tool -change ... ## to change the dependencies
$ install_name_tool -rpath ... -add_rpath ... -delete_rpath ...  ## to change RPATHs

How to assign

Assign the rpath as below. Put the directory path in the {dir} part.

Note that using the #BSD Linker method is also compatible with the #GNU Linker.

MacOSX RPath

You can specify the rpath using DYLD_LIBRARY_PATH, which plays the same role as LD_LIBRARY_PATH on Linux. However, it must be exported. Note that if a library is not found, DYLD_FALLBACK_LIBRARY_PATH is consulted.

You probably won't need them often, but commercial Unix systems use the following environment variables.

  • Solaris: LD_LIBRARY_PATH
  • AIX: LIBPATH
  • HP-UX: SHLIB_PATH

Install name

(This section can be reached via install_name.)

A path name embedded in a dynamic library to tell the linker where to find that dynamic library at runtime.

@executable_path
Useful for frameworks embedded inside applications, because it allows you to specify the location of the framework relative to the application’s executable
If, when writing an application, you cannot install a framework in /Library or a similar location and must embed it inside the application, setting the install name to an absolute path becomes an awkward problem.
The Mac solution for this case is @executable_path. If you set a library's install name to start with @executable_path, that string is replaced with the path from which the executable was loaded.
For example, if you link Bar.app with Foo.framework and Bar.app is installed in /Applications, @executable_path expands to /Applications/Bar.app/Contents/MacOS. If you want to include the framework in Contents/frameworks, just set the install name of Foo.frameworks to @executable_path/../Frameworks/Foo.framework/Versions/A/Foo.
The dynamic linker expands this path to /Applications/Bar.app/Contents/MacOS/../Frameworks/Foo.framework/Versions/A/Foo to find the framework.
@loader_path
Available from Mac OS X 10.4 Tiger onwards; useful for frameworks embedded inside plug-ins, because it allows you to specify the location of the framework relative to the plug-in’s code (remember, plug-ins may not actually know where they are going to be installed, relative to the application, so knowing @executable_path doesn’t help us in this case)
Sometimes the location of the executable alone is not enough. Consider a framework or plug-in that embeds another framework. Say Foo.framework embeds Baz.framework. It is Foo.framework that requests Baz.framework to be loaded, but the dynamic linker uses the path of Bar.app for @executable_path, and this cannot work properly.
Use @loader_path, available since Mac OS 10.4. Its value is the full path, excluding the last path component, of whatever caused the target library to be loaded (whether a framework or a plug-in).
@rpath
@rpath instructs the dynamic linker to search a list of paths in order to locate the framework
In theory the above should be enough, but in practice there are cases where it is a problem. The problem is that a single copy of a library can only be used in one way. If you want Foo.framework to work both when embedded in some application and when installed in /Libary/Frameworks, you have to distribute two versions of the framework, each with its own install name. Or you have to modify the install name during installation with the install_name_tool command. In the end it is possible, but still an awkward problem.
Since Mac OS 1.05, you can solve this problem with @rpath. If the install name starts with @rpath, the dynamic linker searches a list recording library locations. Because this list is included in the application, it is created when the application is built, not when the framework is built. So a single copy of a framework can be used for various purposes at the time the application is made.
To make this work, the install name of Foo.framework must be set to @rpath/Foo.framework/Versions/A/Foo. An application that embeds Foo.framework passes the -rpath @executable_path/../Frameworks option to the linker at build time. This makes the dynamic linker look for the framework at the given path instead of @rpath. An application that installs Foo.framework in /Library/Frameworks can use the -rpath /Library/Frameworks link option so that the dynamic linker looks in that path. If for some reason you don't want to choose between the two at build time, just pass both options to the linker, and the dynamic linker will try both paths to find the framework.

How to use

$ clang foo.c -dynamiclib -install_name @executable_path/../foo/libfoo.dylib -o libfoo.dylib

Documentation

Ns-3_Application_Note_-_linker-problems.pdf
A summary of linker-related problems.

See also

Favorite site

References


  1. 3.18.10 Darwin Options ↩

  2. Adding and managing System Libraries (ldconfig command, /etc/ld.so.conf.d files) ↩

  3. Glibc_-_shared_library_symbol_version.pdf ↩

  4. Out_of_Bedlam_-_Mac_OS_X_Linking_and_Install_Names.pdf ↩

  5. Using_static_and_shared_libraries_across_platforms.pdf ↩

  6. Korea.gnu.org.zip - manual/release/ld/ld-sjp/ld-ko_toc.html ↩

author Zer0 sitemap