Skip to content

Commit

Permalink
Merge pull request #17702 from rootbeer/correct-libc-nonshared
Browse files Browse the repository at this point in the history
Fix libc_nonshared.a
  • Loading branch information
andrewrk authored Jan 5, 2024
2 parents d3a163f + 362460e commit 4583667
Show file tree
Hide file tree
Showing 30 changed files with 922 additions and 544 deletions.
83 changes: 83 additions & 0 deletions lib/libc/glibc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Zig GNU C Library ("glibc") Support

Zig supports building binaries that will dynamically link against the
[GNU C Library ("glibc")](https://www.gnu.org/software/libc/) 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](https://musl.libc.org/) 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.

## 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 `#ifdef`s 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
https://github.com/ziglang/zig/commit/2314051acaad37dd5630dd7eca08571d620d6496
for an example commit that updates glibc (to v2.38).
12 changes: 12 additions & 0 deletions lib/libc/glibc/include/libc-symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,18 @@
extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))) \
__attribute_copy__ (name);

/* Zig patch. weak_hidden_alias was removed from glibc v2.36 (v2.37?), Zig
needs it for the v2.32 and earlier {f,l,}stat wrappers, so only include
in this header for 2.32 and earlier. */
#if (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 32) || __GLIBC__ < 2
# define weak_hidden_alias(name, aliasname) \
_weak_hidden_alias (name, aliasname)
# define _weak_hidden_alias(name, aliasname) \
extern __typeof (name) aliasname \
__attribute__ ((weak, alias (#name), __visibility__ ("hidden"))) \
__attribute_copy__ (name);
#endif

/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */
# define weak_extern(symbol) _weak_extern (weak symbol)
# define _weak_extern(expr) _Pragma (#expr)
Expand Down
55 changes: 55 additions & 0 deletions lib/libc/glibc/io/fstat-2.32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* Copyright (C) 1996-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */

#include <sys/stat.h>

/* This definition is only used if inlining fails for this function; see
the last page of <sys/stat.h>. The real work is done by the `x'
function which is passed a version number argument. We arrange in the
makefile that when not inlined this function is always statically
linked; that way a dynamically-linked executable always encodes the
version number corresponding to the data structures it uses, so the `x'
functions in the shared library can adapt without needing to recompile
all callers. */

#undef fstat
#undef __fstat
int
attribute_hidden
__fstat (int fd, struct stat *buf)
{
return __fxstat (_STAT_VER, fd, buf);
}

weak_hidden_alias (__fstat, fstat)
52 changes: 52 additions & 0 deletions lib/libc/glibc/io/fstat64-2.32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* Copyright (C) 1996-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */

#include <sys/stat.h>

/* This definition is only used if inlining fails for this function; see
the last page of <sys/stat.h>. The real work is done by the `x'
function which is passed a version number argument. We arrange in the
makefile that when not inlined this function is always statically
linked; that way a dynamically-linked executable always encodes the
version number corresponding to the data structures it uses, so the `x'
functions in the shared library can adapt without needing to recompile
all callers. */

#undef fstat64
int
attribute_hidden
fstat64 (int fd, struct stat64 *buf)
{
return __fxstat64 (_STAT_VER, fd, buf);
}
52 changes: 52 additions & 0 deletions lib/libc/glibc/io/fstatat-2.32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* Copyright (C) 2005-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */

#include <sys/stat.h>

/* This definition is only used if inlining fails for this function; see
the last page of <sys/stat.h>. The real work is done by the `x'
function which is passed a version number argument. We arrange in the
makefile that when not inlined this function is always statically
linked; that way a dynamically-linked executable always encodes the
version number corresponding to the data structures it uses, so the `x'
functions in the shared library can adapt without needing to recompile
all callers. */

#undef fstatat
int
attribute_hidden
fstatat (int fd, const char *file, struct stat *buf, int flag)
{
return __fxstatat (_STAT_VER, fd, file, buf, flag);
}
52 changes: 52 additions & 0 deletions lib/libc/glibc/io/fstatat64-2.32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* Copyright (C) 2005-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */

#include <sys/stat.h>

/* This definition is only used if inlining fails for this function; see
the last page of <sys/stat.h>. The real work is done by the `x'
function which is passed a version number argument. We arrange in the
makefile that when not inlined this function is always statically
linked; that way a dynamically-linked executable always encodes the
version number corresponding to the data structures it uses, so the `x'
functions in the shared library can adapt without needing to recompile
all callers. */

#undef fstatat64
int
attribute_hidden
fstatat64 (int fd, const char *file, struct stat64 *buf, int flag)
{
return __fxstatat64 (_STAT_VER, fd, file, buf, flag);
}
55 changes: 55 additions & 0 deletions lib/libc/glibc/io/lstat-2.32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* Copyright (C) 1996-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Lesser General Public
License, the Free Software Foundation gives you unlimited
permission to link the compiled version of this file with other
programs, and to distribute those programs without any restriction
coming from the use of this file. (The GNU Lesser General Public
License restrictions do apply in other respects; for example, they
cover modification of the file, and distribution when not linked
into another program.)
Note that people who make modified versions of this file are not
obligated to grant this special exception for their modified
versions; it is their choice whether to do so. The GNU Lesser
General Public License gives permission to release a modified
version without this exception; this exception also makes it
possible to release a modified version which carries forward this
exception.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */

#include <sys/stat.h>

/* This definition is only used if inlining fails for this function; see
the last page of <sys/stat.h>. The real work is done by the `x'
function which is passed a version number argument. We arrange in the
makefile that when not inlined this function is always statically
linked; that way a dynamically-linked executable always encodes the
version number corresponding to the data structures it uses, so the `x'
functions in the shared library can adapt without needing to recompile
all callers. */

#undef lstat
#undef __lstat
int
attribute_hidden
__lstat (const char *file, struct stat *buf)
{
return __lxstat (_STAT_VER, file, buf);
}

weak_hidden_alias (__lstat, lstat)
Loading

0 comments on commit 4583667

Please sign in to comment.