How glibc 2.27 relocates a statically linked executable
glibc 2.27 adds static PIE support on selected architectures. The startup implementation explains how a static executable can accept a variable load address without an external dynamic linker.
Static linking and a variable load address can coexist, provided the executable performs the relocation work needed before ordinary library code runs. That is the mechanism behind static PIE support in glibc 2.27's release announcement. The library can now produce static executables that load at different addresses without help from a dynamic linker. The change adds a hardening option to a linking model that otherwise includes library code in the executable.
The announcement is explicit about the cost. Static PIE consumes some additional memory and performance. It also requires a compatible compiler, linker and glibc build. Treating it as an unconditional property of every static executable would miss both the implementation and the deployment requirements.
C's importance to me includes its role in platform interfaces and interoperation. Executable startup is part of that practical environment, even though it sits outside the source-language rules most application code uses. Understanding who relocates a program helps explain which guarantees a compiler switch can actually deliver.
Relocation happens inside the executable
The release's static PIE relocation implementation provides a short account of the mechanism. _dl_relocate_static_pie obtains the main executable's link map and computes its runtime load address. It then locates the executable's dynamic section relative to that address and reads the dynamic information needed for relocation.
The function uses the library's existing dynamic relocation machinery with bootstrap definitions that resolve against the main executable's own map. After relocation, it marks that map as relocated. The source comment explains why this must happen before normal execution can proceed. Ordinary function calls and data access through the global offset table need the relocated addresses.
The word static therefore describes how the executable incorporates its libraries. It does not mean that every address embedded in its runtime representation is already correct at an arbitrary load location. The startup code supplies the missing adjustment. A dynamic section inside this executable is information for that adjustment, not evidence that an external dynamic linker must be doing the work.
The 2.27 startup implementation calls _dl_relocate_static_pie in its non-shared path. The call precedes the setup that obtains the environment pointer and records the lowest stack address. Its placement makes the ordering requirement concrete. Relocation belongs near the start of library initialization because later startup operations need ordinary access to code and data.
This arrangement also explains why a library build is involved. A compiler option cannot retroactively make an unsuitable startup implementation bootstrap itself. The executable needs startup code compiled for the intended model, as well as the appropriate library objects and linker output.
The build option changes more than one command
The INSTALL file shipped with glibc 2.27 documents --enable-static-pie. With that configuration, static programs and static tests use static PIE except where they are marked no-pie. The option also makes glibc's dynamic programs and tests position-independent executables by default.
Applications use the resulting library with GCC's -static-pie option. The release specifies GCC 8 or above, which is a toolchain requirement, not a claim that every compiler currently installed has the option. A schematic application build against such a toolchain is:
gcc -static-pie hello.c -o hello
That command assumes the compiler option and a suitable glibc build are both available. It does not configure the C library. Keeping those steps distinct matters when a system compiler and a separately built library have different capabilities. A successful library configuration is one prerequisite for the final application link.
Architecture support is also bounded. The announcement lists i386, x86-64 and x32 with binutils 2.29 or later. AArch64 requires binutils 2.30 or later. These are the supported combinations announced for this release. The existence of glibc on another architecture does not establish static PIE support there.
A movable executable is one hardening property
The new property is that the static executable can load at any address. This permits address variation instead of requiring the program to occupy one fixed location. The announcement describes the resulting security hardening while acknowledging its resource costs. It does not claim that the program's own memory accesses become checked or that invalid C operations gain defined behavior.
That distinction keeps the security argument specific. Relocation changes the addresses at which existing code and data can reside. The application still has the same source-level obligations. Its allocation sizes, pointer lifetimes and access bounds remain separate concerns. Static PIE can be useful without being a replacement for correctness in the program being linked.
I regard the explicit startup mechanism as the strongest part of this change. The implementation identifies the work required to support a variable address and performs it before normal library initialization. That is a more useful basis for evaluating the feature than treating static linking as a general statement about executable safety.
Static programs still consume external data
Another change in the same release gives a concrete limit to deployment independence. glibc 2.27 extends its binary locale-data format to support alternative grammatical forms of month names. The announcement warns that older statically compiled applications cannot load the new locale data and fall back to the built-in C/POSIX locale. Static applications that need locale support must be recompiled to match the runtime data they use.
This is a different compatibility relationship from linking a shared library. The executable includes library code but still reads an external data format. Updating that format can therefore change behavior without replacing code inside the executable. Static PIE changes where the executable can load. It does not change this relationship between embedded library code and external locale data.
The release also deprecates support for statically linked applications that call dlopen, directing such applications toward dynamic linking. Together, these notes constrain the interpretation of the new option. glibc 2.27 supports self-relocating static executables on specified toolchains and architectures, while preserving separate requirements around runtime data and supported loading behavior.