zig/lib/libc/glibc
Andrew Kelley f5485a52bc reject crti.o/crtn.o, embrace the future
crti.o/crtn.o is a legacy strategy for calling constructor functions
upon object loading that has been superseded by the
init_array/fini_array mechanism.

Zig code depends on neither, since the language intentionally has no way
to initialize data at runtime, but alas the Zig linker still must
support this feature since popular languages depend on it.

Anyway, the way it works is that crti.o has the machine code prelude of
two functions called _init and _fini, each in their own section with the
respective name. crtn.o has the machine code instructions comprising the
exitlude for each function. In between, objects use the .init and .fini
link section to populate the function body.

This function is then expected to be called upon object initialization
and deinitialization.

This mechanism is depended on by libc, for example musl and glibc, but
only for older ISAs. By the time the libcs gained support for newer
ISAs, they had moved on to the init_array/fini_array mechanism instead.

For the Zig linker, we are trying to move the linker towards
order-independent objects which is incompatible with the legacy
crti/crtn mechanism.

Therefore, this commit drops support entirely for crti/crtn mechanism,
which is necessary since the other commits in this branch make it
nondeterministic in which order the libc objects and the other link
inputs are sent to the linker.

The linker is still expected to produce a deterministic output, however,
by ignoring object input order for the purposes of symbol resolution.
2025-01-20 20:59:52 -08:00
..
bits Update glibc start files to 2.40. 2024-08-08 04:41:04 +02:00
csu glibc: Define _IO_stdin_used in start code and reference it in stub asm. 2024-08-23 11:09:20 -07:00
debug update glibc start files to 2.39 2024-06-05 22:43:53 -07:00
elf Update glibc start files to 2.40. 2024-08-08 04:41:04 +02:00
include Update glibc start files to 2.40. 2024-08-08 04:41:04 +02:00
io Update glibc start files to 2.40. 2024-08-08 04:41:04 +02:00
locale/bits/types update glibc start files to 2.39 2024-06-05 22:43:53 -07:00
misc Update glibc start files to 2.40. 2024-08-08 04:41:04 +02:00
posix glibc patch: don't check __LIBC macro 2024-06-05 22:43:53 -07:00
signal Update glibc start files to 2.40. 2024-08-08 04:41:04 +02:00
stdlib Update glibc start files to 2.40. 2024-08-08 04:41:04 +02:00
string update glibc start files to 2.39 2024-06-05 22:43:53 -07:00
sysdeps reject crti.o/crtn.o, embrace the future 2025-01-20 20:59:52 -08:00
time/bits/types Update glibc start files to 2.40. 2024-08-08 04:41:04 +02:00
abilists glibc: Update abilists file for loongarch64-linux-gnusf support. 2024-10-03 04:39:39 +02:00
LICENSES update glibc start files to 2.39 2024-06-05 22:43:53 -07:00
README.md test/link/glibc_compat: Add C test case for glibc versions 2024-06-06 09:36:16 -07:00

Zig GNU C Library ("glibc") Support

Zig supports building binaries that will dynamically link against the GNU C Library ("glibc") when run. This support extends across a range of glibc versions.

By default, Zig binaries will not depend on any external C library, but they can be linked against one with the -lc option. The target ABI defines which C library: musl for the musl C library or gnu for the GNU C library.

A specific GNU C library version can be chosen with an appropriate -target. For example, -target native-native-gnu.2.19 will use the default CPU and OS targets, but will link in a run-time dependency on glibc v2.19 (or later). Use zig env to show the default target and version.

Glibc symbols are defined in the std.c. namespace in Zig, though the std.os. namespace is generally what should be used to access C-library APIs in Zig code (it is defined depending on the linked C library).

See src/glibc.zig for how Zig will build the glibc components. The generated shared object files are sufficient only for compile-time linking. They are stub libraries that only indicate that which symbols will be present at run-time, along with their type and size. The symbols do not reference an actual implementation.

Targets

The GNU C Library supports a very wide set of platforms and architectures. The current Zig support for glibc only includes Linux.

Zig supports glibc versions back to v2.17 (2012) as the Zig standard library depends on symbols that were introduced in 2.17. When used as a C or C++ compiler (i.e., zig cc) zig supports glibc versions back to v2.2.5.

Glibc stubs

The file lib/libc/glibc/abilist is a Zig-specific binary blob that defines the supported glibc versions and the set of symbols each version must define. See https://github.com/ziglang/glibc-abi-tool for the tooling to generate this blob. The code in glibc.zig parses the abilist to build version-specific stub libraries on demand.

The generated stub library is used for compile-time linking, with the expectation that at run-time the real glibc library will provide the actual symbol implementations.

Public Headers

The glibc headers are in lib/libc/include/generic-glibc/. These are customized and have a couple Zig-specific #ifdefs to make the single set of headers represent any of the supported glibc versions. There are currently a handful of patches to these headers to represent new features (e.g. reallocarray) or changes in implementation (e.g., the stat() family of functions).

The related Zig https://github.com/ziglang/universal-headers is a project designed to more robustly build multi-version header files suitable for compilation across a variety of target C library versions.

Glibc static C-Runtime object files and libraries

Linking against glibc also implies linking against several, generally "invisible" glibc C Runtime libraries: crti.o, crtn.o, Scrt1.o and libc_nonshared.a. These objects are linked into generated Zig binaries and are not run-time linking dependencies. Generally they provide bootstrapping, initialization, and mapping of un-versioned public APIs to glibc-private versioned APIs.

Like the public headers, these files contain a couple customiziations for Zig to be able to build for any supported glibc version. E.g., for glibc versions before v2.32, libc_nonshared.a contained stubs that directed the fstat() call to a versioned __fxstat() call.

These files used for these objects are in lib/libc/glibc. See the tools/update_glibc.zig tool for updating content in here from the upstream glibc.

More Information

See 2314051aca for an example commit that updates glibc (to v2.38).