LinuxCommandLibrary

ld

Link object files to create executables

TLDR

Link a specific object file with no dependencies into an executable

$ ld [path/to/file.o] [[-o|--output]] [path/to/output_executable]
copy

Link two object files together
$ ld [path/to/file1.o] [path/to/file2.o] [[-o|--output]] [path/to/output_executable]
copy

Dynamically link an x86_64 program to glibc (file paths change depending on the system)
$ ld [[-o|--output]] [path/to/output_executable] [[-I|--dynamic-linker]] /lib/ld-linux-x86-64.so.2 /lib/crt1.o /lib/crti.o -lc [path/to/file.o] /lib/crtn.o
copy

SYNOPSIS

ld [options] objfile...

PARAMETERS

-o outputfile
    Specifies the name of the output file created by the linker. If not specified, a.out is used by default.

-L dir
    Adds dir to the list of directories that ld searches for libraries. This option is crucial when linking against custom or non-standard libraries.

-l name
    Searches for the library named libname.a or libname.so. The linker first tries the shared version, then the static version, in the directories specified by -L.

-rpath dir
    Adds dir to the runtime library search path encoded in the output executable. This allows the program to find shared libraries at runtime in specified locations.

-static
    Performs static linking, meaning all necessary library code is embedded directly into the executable, making it self-contained and not dependent on shared libraries at runtime.

-shared
    Creates a shared library (dynamic library) instead of an executable file. This library can then be linked against by other programs or loaded at runtime.

-e entry
    Sets the entry point address for the executable. This specifies where program execution begins when the executable is run.

-T scriptfile
    Uses scriptfile as the linker script. Linker scripts provide fine-grained control over the output file's layout, memory mapping, and symbol placement.

--version
-v

    Prints the version number of the ld program.

--verbose
    Prints detailed information about the linker's operation, including the linker script used and libraries found.

-S
--strip-debug

    Strips debugging symbols from the output file, reducing its size.

-x
--discard-all

    Discards all local symbols from the output file, similar to -S but also removes other non-global symbols.

DESCRIPTION

The ld command, often referred to as the GNU linker, is a fundamental utility in the software development process on Linux systems. Its primary role is to take one or more object files (produced by a compiler) and archive files (libraries) as input, then combine them into a single executable program, a shared library, or another object file. During this crucial process, ld resolves symbol references between different input files, assigns addresses to various code and data sections, and performs necessary relocations. It's responsible for mapping program segments (like .text for code, .data for initialized data, and .bss for uninitialized data) to specific memory locations within the output file. While developers often interact with ld indirectly via front-end compilers like gcc, understanding its direct usage and capabilities is vital for advanced tasks such as creating custom memory layouts or optimizing binary sizes. ld relies on a linker script, either a default one or a user-provided custom script, to define how the output sections are structured and how symbols are resolved.

CAVEATS

ld is most commonly invoked indirectly by high-level compilers like gcc. Direct invocation is typically reserved for specialized linking tasks, such as creating embedded system firmware or manipulating the linker script.
Errors related to 'undefined references' are frequently encountered and usually indicate that a required library was not linked (missing -l or -L options) or that a symbol is not visible (e.g., due to C++ name mangling or incorrect declaration/definition).
Linker scripts provide immense power but require a deep understanding of the executable format (e.g., ELF) and memory layout, making them complex to write and debug.

LINKER SCRIPTS

ld utilizes linker scripts to provide precise control over the linking process. These plain-text files allow developers to define how input sections from object files are mapped to output sections, specify the layout of the output file in memory, and control symbol placement. They are indispensable for advanced scenarios such as optimizing memory usage in embedded systems, creating custom executable formats, or placing specific code/data segments at fixed memory addresses.

DYNAMIC VS. STATIC LINKING

ld supports two primary linking models: dynamic (shared) and static. Dynamic linking (default for many systems) creates smaller executables by referencing shared libraries that are loaded at runtime. This saves disk space and memory but introduces a dependency on the presence and version of those libraries. Static linking, enabled by the -static option, embeds all necessary library code directly into the executable, resulting in larger, self-contained binaries that have no runtime dependencies on shared libraries, offering greater portability but increased executable size.

HISTORY

The ld command has roots in early Unix systems, serving as the fundamental tool for assembling executable programs. The GNU ld, part of the GNU Binutils collection, was developed as a free and open-source alternative to proprietary linkers. Its evolution has closely mirrored advancements in computing architectures and operating systems, adapting to new binary formats like ELF (Executable and Linkable Format), which is standard on Linux. Over decades, it has become the de facto linker for the GNU/Linux ecosystem, offering extensive support for various architectures and sophisticated customization through linker scripts, continually updated to meet modern software development demands.

SEE ALSO

gcc(1), ar(1), nm(1), objdump(1), readelf(1), strip(1)

Copied to clipboard