authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-04 16:28:39-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-01-04 16:28:39-08:00
log45836678d76014f94d35a2ffea983c21a57426c4
tree2cdeb8469c1cda5b6d50b86f38d87c4b5a3ea2b1
parentd3a163f86845bcc7d20e5fd54174e480d1a8ac33
parent362460ec24d802e6fba7f45ddff5f969642839df
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #17702 from rootbeer/correct-libc-nonshared

Fix libc_nonshared.a

30 files changed, 922 insertions(+), 544 deletions(-)

lib/libc/glibc/README.md created+83
...@@ -0,0 +1,83 @@
1# Zig GNU C Library ("glibc") Support
2
3Zig supports building binaries that will dynamically link against the
4[GNU C Library ("glibc")](https://www.gnu.org/software/libc/) when run.
5This support extends across a range of glibc versions.
6
7By default, Zig binaries will not depend on any external C library, but
8they can be linked against one with the `-lc` option. The target ABI defines
9which C library: `musl` for the [musl C library](https://musl.libc.org/) or
10`gnu` for the GNU C library.
11
12A specific GNU C library version can be chosen with an appropriate
13`-target`. For example, `-target native-native-gnu.2.19` will use the
14default CPU and OS targets, but will link in a run-time dependency on
15glibc v2.19 (or later). Use `zig env` to show the default target and
16version.
17
18Glibc symbols are defined in the `std.c.` namespace in Zig, though the
19`std.os.` namespace is generally what should be used to access C-library
20APIs in Zig code (it is defined depending on the linked C library).
21
22See `src/glibc.zig` for how Zig will build the glibc components. The
23generated shared object files are sufficient only for compile-time
24linking. They are stub libraries that only indicate that which symbols
25will be present at run-time, along with their type and size. The symbols
26do not reference an actual implementation.
27
28## Targets
29
30The GNU C Library supports a very wide set of platforms and architectures.
31The current Zig support for glibc only includes Linux.
32
33Zig supports glibc versions back to v2.17 (2012) as the Zig standard
34library depends on symbols that were introduced in 2.17.
35
36## Glibc stubs
37
38The file `lib/libc/glibc/abilist` is a Zig-specific binary blob that
39defines the supported glibc versions and the set of symbols each version
40must define. See https://github.com/ziglang/glibc-abi-tool for the
41tooling to generate this blob. The code in `glibc.zig` parses the abilist
42to build version-specific stub libraries on demand.
43
44The generated stub library is used for compile-time linking, with the
45expectation that at run-time the real glibc library will provide the
46actual symbol implementations.
47
48### Public Headers
49
50The glibc headers are in `lib/libc/include/generic-glibc/`. These are
51customized and have a couple Zig-specific `#ifdef`s to make the single set
52of headers represent any of the supported glibc versions. There are
53currently a handful of patches to these headers to represent new features
54(e.g. `reallocarray`) or changes in implementation (e.g., the `stat()`
55family of functions).
56
57The related Zig https://github.com/ziglang/universal-headers is a project
58designed to more robustly build multi-version header files suitable for
59compilation across a variety of target C library versions.
60
61## Glibc static C-Runtime object files and libraries
62
63Linking against glibc also implies linking against several, generally
64"invisible" glibc C Runtime libraries: `crti.o`, `crtn.o`, `Scrt1.o` and
65`libc_nonshared.a`. These objects are linked into generated Zig binaries
66and are not run-time linking dependencies. Generally they provide
67bootstrapping, initialization, and mapping of un-versioned public APIs to
68glibc-private versioned APIs.
69
70Like the public headers, these files contain a couple customiziations for
71Zig to be able to build for any supported glibc version. E.g., for glibc
72versions before v2.32, `libc_nonshared.a` contained stubs that directed
73the `fstat()` call to a versioned `__fxstat()` call.
74
75These files used for these objects are in `lib/libc/glibc`. See the
76`tools/update_glibc.zig` tool for updating content in here from the
77upstream glibc.
78
79# More Information
80
81See
82https://github.com/ziglang/zig/commit/2314051acaad37dd5630dd7eca08571d620d6496
83for an example commit that updates glibc (to v2.38).
lib/libc/glibc/include/libc-symbols.h+12
...@@ -155,6 +155,18 @@...@@ -155,6 +155,18 @@
155 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))) \155 extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))) \
156 __attribute_copy__ (name);156 __attribute_copy__ (name);
157157
158/* Zig patch. weak_hidden_alias was removed from glibc v2.36 (v2.37?), Zig
159 needs it for the v2.32 and earlier {f,l,}stat wrappers, so only include
160 in this header for 2.32 and earlier. */
161#if (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 32) || __GLIBC__ < 2
162# define weak_hidden_alias(name, aliasname) \
163 _weak_hidden_alias (name, aliasname)
164# define _weak_hidden_alias(name, aliasname) \
165 extern __typeof (name) aliasname \
166 __attribute__ ((weak, alias (#name), __visibility__ ("hidden"))) \
167 __attribute_copy__ (name);
168#endif
169
158/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */170/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */
159# define weak_extern(symbol) _weak_extern (weak symbol)171# define weak_extern(symbol) _weak_extern (weak symbol)
160# define _weak_extern(expr) _Pragma (#expr)172# define _weak_extern(expr) _Pragma (#expr)
lib/libc/glibc/io/fstat-2.32.c created+55
...@@ -0,0 +1,55 @@
1/* Copyright (C) 1996-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
24 exception.
25
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
30
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, see
33 <https://www.gnu.org/licenses/>. */
34
35#include <sys/stat.h>
36
37/* This definition is only used if inlining fails for this function; see
38 the last page of <sys/stat.h>. The real work is done by the `x'
39 function which is passed a version number argument. We arrange in the
40 makefile that when not inlined this function is always statically
41 linked; that way a dynamically-linked executable always encodes the
42 version number corresponding to the data structures it uses, so the `x'
43 functions in the shared library can adapt without needing to recompile
44 all callers. */
45
46#undef fstat
47#undef __fstat
48int
49attribute_hidden
50__fstat (int fd, struct stat *buf)
51{
52 return __fxstat (_STAT_VER, fd, buf);
53}
54
55weak_hidden_alias (__fstat, fstat)
lib/libc/glibc/io/fstat64-2.32.c created+52
...@@ -0,0 +1,52 @@
1/* Copyright (C) 1996-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
24 exception.
25
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
30
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, see
33 <https://www.gnu.org/licenses/>. */
34
35#include <sys/stat.h>
36
37/* This definition is only used if inlining fails for this function; see
38 the last page of <sys/stat.h>. The real work is done by the `x'
39 function which is passed a version number argument. We arrange in the
40 makefile that when not inlined this function is always statically
41 linked; that way a dynamically-linked executable always encodes the
42 version number corresponding to the data structures it uses, so the `x'
43 functions in the shared library can adapt without needing to recompile
44 all callers. */
45
46#undef fstat64
47int
48attribute_hidden
49fstat64 (int fd, struct stat64 *buf)
50{
51 return __fxstat64 (_STAT_VER, fd, buf);
52}
lib/libc/glibc/io/fstatat-2.32.c created+52
...@@ -0,0 +1,52 @@
1/* Copyright (C) 2005-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
24 exception.
25
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
30
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, see
33 <https://www.gnu.org/licenses/>. */
34
35#include <sys/stat.h>
36
37/* This definition is only used if inlining fails for this function; see
38 the last page of <sys/stat.h>. The real work is done by the `x'
39 function which is passed a version number argument. We arrange in the
40 makefile that when not inlined this function is always statically
41 linked; that way a dynamically-linked executable always encodes the
42 version number corresponding to the data structures it uses, so the `x'
43 functions in the shared library can adapt without needing to recompile
44 all callers. */
45
46#undef fstatat
47int
48attribute_hidden
49fstatat (int fd, const char *file, struct stat *buf, int flag)
50{
51 return __fxstatat (_STAT_VER, fd, file, buf, flag);
52}
lib/libc/glibc/io/fstatat64-2.32.c created+52
...@@ -0,0 +1,52 @@
1/* Copyright (C) 2005-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
24 exception.
25
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
30
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, see
33 <https://www.gnu.org/licenses/>. */
34
35#include <sys/stat.h>
36
37/* This definition is only used if inlining fails for this function; see
38 the last page of <sys/stat.h>. The real work is done by the `x'
39 function which is passed a version number argument. We arrange in the
40 makefile that when not inlined this function is always statically
41 linked; that way a dynamically-linked executable always encodes the
42 version number corresponding to the data structures it uses, so the `x'
43 functions in the shared library can adapt without needing to recompile
44 all callers. */
45
46#undef fstatat64
47int
48attribute_hidden
49fstatat64 (int fd, const char *file, struct stat64 *buf, int flag)
50{
51 return __fxstatat64 (_STAT_VER, fd, file, buf, flag);
52}
lib/libc/glibc/io/lstat-2.32.c created+55
...@@ -0,0 +1,55 @@
1/* Copyright (C) 1996-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
24 exception.
25
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
30
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, see
33 <https://www.gnu.org/licenses/>. */
34
35#include <sys/stat.h>
36
37/* This definition is only used if inlining fails for this function; see
38 the last page of <sys/stat.h>. The real work is done by the `x'
39 function which is passed a version number argument. We arrange in the
40 makefile that when not inlined this function is always statically
41 linked; that way a dynamically-linked executable always encodes the
42 version number corresponding to the data structures it uses, so the `x'
43 functions in the shared library can adapt without needing to recompile
44 all callers. */
45
46#undef lstat
47#undef __lstat
48int
49attribute_hidden
50__lstat (const char *file, struct stat *buf)
51{
52 return __lxstat (_STAT_VER, file, buf);
53}
54
55weak_hidden_alias (__lstat, lstat)
lib/libc/glibc/io/lstat64-2.32.c created+52
...@@ -0,0 +1,52 @@
1/* Copyright (C) 1996-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
24 exception.
25
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
30
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, see
33 <https://www.gnu.org/licenses/>. */
34
35#include <sys/stat.h>
36
37/* This definition is only used if inlining fails for this function; see
38 the last page of <sys/stat.h>. The real work is done by the `x'
39 function which is passed a version number argument. We arrange in the
40 makefile that when not inlined this function is always statically
41 linked; that way a dynamically-linked executable always encodes the
42 version number corresponding to the data structures it uses, so the `x'
43 functions in the shared library can adapt without needing to recompile
44 all callers. */
45
46#undef lstat64
47int
48attribute_hidden
49lstat64 (const char *file, struct stat64 *buf)
50{
51 return __lxstat64 (_STAT_VER, file, buf);
52}
lib/libc/glibc/io/mknod-2.32.c created+55
...@@ -0,0 +1,55 @@
1/* Copyright (C) 1995-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
24 exception.
25
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
30
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, see
33 <https://www.gnu.org/licenses/>. */
34
35
36#include <sys/types.h>
37#include <sys/stat.h>
38
39/* This definition is only used if inlining fails for this function; see
40 the last page of <sys/stat.h>. The real work is done by the `x'
41 function which is passed a version number argument. We arrange in the
42 makefile that when not inlined this function is always statically
43 linked; that way a dynamically-linked executable always encodes the
44 version number corresponding to the data structures it uses, so the `x'
45 functions in the shared library can adapt without needing to recompile
46 all callers. */
47
48int
49attribute_hidden
50__mknod (const char *path, mode_t mode, dev_t dev)
51{
52 return __xmknod (_MKNOD_VER, path, mode, &dev);
53}
54
55weak_hidden_alias (__mknod, mknod)
lib/libc/glibc/io/mknodat-2.32.c created+53
...@@ -0,0 +1,53 @@
1/* Copyright (C) 1995-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
24 exception.
25
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
30
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, see
33 <https://www.gnu.org/licenses/>. */
34
35
36#include <sys/types.h>
37#include <sys/stat.h>
38
39/* This definition is only used if inlining fails for this function; see
40 the last page of <sys/stat.h>. The real work is done by the `x'
41 function which is passed a version number argument. We arrange in the
42 makefile that when not inlined this function is always statically
43 linked; that way a dynamically-linked executable always encodes the
44 version number corresponding to the data structures it uses, so the `x'
45 functions in the shared library can adapt without needing to recompile
46 all callers. */
47
48int
49attribute_hidden
50mknodat (int fd, const char *path, mode_t mode, dev_t dev)
51{
52 return __xmknodat (_MKNOD_VER, fd, path, mode, &dev);
53}
lib/libc/glibc/io/stat-2.32.c created+54
...@@ -0,0 +1,54 @@
1/* Copyright (C) 1996-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
24 exception.
25
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
30
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, see
33 <https://www.gnu.org/licenses/>. */
34
35#include <sys/stat.h>
36
37/* This definition is only used if inlining fails for this function; see
38 the last page of <sys/stat.h>. The real work is done by the `x'
39 function which is passed a version number argument. We arrange in the
40 makefile that when not inlined this function is always statically
41 linked; that way a dynamically-linked executable always encodes the
42 version number corresponding to the data structures it uses, so the `x'
43 functions in the shared library can adapt without needing to recompile
44 all callers. */
45
46#undef stat
47int
48attribute_hidden
49__stat (const char *file, struct stat *buf)
50{
51 return __xstat (_STAT_VER, file, buf);
52}
53
54weak_hidden_alias (__stat, stat)
lib/libc/glibc/io/stat64-2.32.c created+52
...@@ -0,0 +1,52 @@
1/* Copyright (C) 1996-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 In addition to the permissions in the GNU Lesser General Public
10 License, the Free Software Foundation gives you unlimited
11 permission to link the compiled version of this file with other
12 programs, and to distribute those programs without any restriction
13 coming from the use of this file. (The GNU Lesser General Public
14 License restrictions do apply in other respects; for example, they
15 cover modification of the file, and distribution when not linked
16 into another program.)
17
18 Note that people who make modified versions of this file are not
19 obligated to grant this special exception for their modified
20 versions; it is their choice whether to do so. The GNU Lesser
21 General Public License gives permission to release a modified
22 version without this exception; this exception also makes it
23 possible to release a modified version which carries forward this
24 exception.
25
26 The GNU C Library is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29 Lesser General Public License for more details.
30
31 You should have received a copy of the GNU Lesser General Public
32 License along with the GNU C Library; if not, see
33 <https://www.gnu.org/licenses/>. */
34
35#include <sys/stat.h>
36
37/* This definition is only used if inlining fails for this function; see
38 the last page of <sys/stat.h>. The real work is done by the `x'
39 function which is passed a version number argument. We arrange in the
40 makefile that when not inlined this function is always statically
41 linked; that way a dynamically-linked executable always encodes the
42 version number corresponding to the data structures it uses, so the `x'
43 functions in the shared library can adapt without needing to recompile
44 all callers. */
45
46#undef stat64
47int
48attribute_hidden
49stat64 (const char *file, struct stat64 *buf)
50{
51 return __xstat64 (_STAT_VER, file, buf);
52}
lib/libc/glibc/sysdeps/unix/sysv/linux/alpha/kernel_stat.h deleted-91
...@@ -1,91 +0,0 @@
1/* Definition of `struct stat' used in the kernel. */
2struct kernel_stat
3 {
4 unsigned int st_dev;
5 unsigned int st_ino;
6 unsigned int st_mode;
7 unsigned int st_nlink;
8 unsigned int st_uid;
9 unsigned int st_gid;
10 unsigned int st_rdev;
11 long int st_size;
12 unsigned long int st_atime_sec;
13 unsigned long int st_mtime_sec;
14 unsigned long int st_ctime_sec;
15 unsigned int st_blksize;
16 int st_blocks;
17 unsigned int st_flags;
18 unsigned int st_gen;
19 };
20
21/* Definition of `struct stat64' used in the kernel. */
22struct kernel_stat64
23 {
24 unsigned long st_dev;
25 unsigned long st_ino;
26 unsigned long st_rdev;
27 long st_size;
28 unsigned long st_blocks;
29
30 unsigned int st_mode;
31 unsigned int st_uid;
32 unsigned int st_gid;
33 unsigned int st_blksize;
34 unsigned int st_nlink;
35 unsigned int __pad0;
36
37 unsigned long st_atime_sec;
38 unsigned long st_atimensec;
39 unsigned long st_mtime_sec;
40 unsigned long st_mtimensec;
41 unsigned long st_ctime_sec;
42 unsigned long st_ctimensec;
43 long __glibc_reserved[3];
44 };
45
46/* Definition of `struct stat' used by glibc 2.0. */
47struct glibc2_stat
48 {
49 __dev_t st_dev;
50 __ino_t st_ino;
51 __mode_t st_mode;
52 __nlink_t st_nlink;
53 __uid_t st_uid;
54 __gid_t st_gid;
55 __dev_t st_rdev;
56 __off_t st_size;
57 __time_t st_atime_sec;
58 __time_t st_mtime_sec;
59 __time_t st_ctime_sec;
60 unsigned int st_blksize;
61 int st_blocks;
62 unsigned int st_flags;
63 unsigned int st_gen;
64 };
65
66/* Definition of `struct stat' used by glibc 2.1. */
67struct glibc21_stat
68 {
69 __dev_t st_dev;
70 __ino64_t st_ino;
71 __mode_t st_mode;
72 __nlink_t st_nlink;
73 __uid_t st_uid;
74 __gid_t st_gid;
75 __dev_t st_rdev;
76 __off_t st_size;
77 __time_t st_atime_sec;
78 __time_t st_mtime_sec;
79 __time_t st_ctime_sec;
80 __blkcnt64_t st_blocks;
81 __blksize_t st_blksize;
82 unsigned int st_flags;
83 unsigned int st_gen;
84 int __pad3;
85 long __glibc_reserved[4];
86 };
87
88#define STAT_IS_KERNEL_STAT 0
89#define STAT64_IS_KERNEL_STAT64 1
90#define XSTAT_IS_XSTAT64 1
91#define STATFS_IS_STATFS64 0
lib/libc/glibc/sysdeps/unix/sysv/linux/arm/kernel_stat.h deleted-40
...@@ -1,40 +0,0 @@
1/* Definition of `struct stat' used in the kernel.. */
2struct kernel_stat
3 {
4 unsigned short int st_dev;
5 unsigned short int __pad1;
6#define _HAVE___PAD1
7 unsigned long int st_ino;
8 unsigned short int st_mode;
9 unsigned short int st_nlink;
10 unsigned short int st_uid;
11 unsigned short int st_gid;
12 unsigned short int st_rdev;
13 unsigned short int __pad2;
14#define _HAVE___PAD2
15 unsigned long int st_size;
16 unsigned long int st_blksize;
17 unsigned long int st_blocks;
18 struct timespec st_atim;
19 struct timespec st_mtim;
20 struct timespec st_ctim;
21 unsigned long int __glibc_reserved4;
22#define _HAVE___UNUSED4
23 unsigned long int __glibc_reserved5;
24#define _HAVE___UNUSED5
25 };
26
27#define _HAVE_STAT___UNUSED4
28#define _HAVE_STAT___UNUSED5
29#define _HAVE_STAT___PAD1
30#define _HAVE_STAT___PAD2
31#define _HAVE_STAT_NSEC
32#define _HAVE_STAT64___PAD1
33#define _HAVE_STAT64___PAD2
34#define _HAVE_STAT64___ST_INO
35#define _HAVE_STAT64_NSEC
36
37#define STAT_IS_KERNEL_STAT 0
38#define STAT64_IS_KERNEL_STAT64 1
39#define XSTAT_IS_XSTAT64 0
40#define STATFS_IS_STATFS64 0
lib/libc/glibc/sysdeps/unix/sysv/linux/hppa/kernel_stat.h deleted-36
...@@ -1,36 +0,0 @@
1/* definition of "struct stat" from the kernel */
2struct kernel_stat {
3 unsigned long st_dev; /* dev_t is 32 bits on parisc */
4 unsigned long st_ino; /* 32 bits */
5 unsigned short st_mode; /* 16 bits */
6 unsigned short st_nlink; /* 16 bits */
7 unsigned short st_reserved1; /* old st_uid */
8 unsigned short st_reserved2; /* old st_gid */
9 unsigned long st_rdev;
10 unsigned long st_size;
11 struct timespec st_atim;
12 struct timespec st_mtim;
13 struct timespec st_ctim;
14 long st_blksize;
15 long st_blocks;
16 unsigned long __glibc_reserved1; /* ACL stuff */
17 unsigned long __glibc_reserved2; /* network */
18 unsigned long __glibc_reserved3; /* network */
19 unsigned long __glibc_reserved4; /* cnodes */
20 unsigned short __glibc_reserved5; /* netsite */
21 short st_fstype;
22 unsigned long st_realdev;
23 unsigned short st_basemode;
24 unsigned short st_spareshort;
25 unsigned long st_uid;
26 unsigned long st_gid;
27 unsigned long st_spare4[3];
28};
29
30#define _HAVE_STAT_NSEC
31#define _HAVE_STAT64_NSEC
32
33#define STAT_IS_KERNEL_STAT 0
34#define STAT64_IS_KERNEL_STAT64 1
35#define XSTAT_IS_XSTAT64 0
36#define STATFS_IS_STATFS64 0
lib/libc/glibc/sysdeps/unix/sysv/linux/i386/kernel_stat.h deleted-40
...@@ -1,40 +0,0 @@
1/* Definition of `struct stat' used in the kernel.. */
2struct kernel_stat
3 {
4 unsigned short int st_dev;
5 unsigned short int __pad1;
6#define _HAVE___PAD1
7 unsigned long int st_ino;
8 unsigned short int st_mode;
9 unsigned short int st_nlink;
10 unsigned short int st_uid;
11 unsigned short int st_gid;
12 unsigned short int st_rdev;
13 unsigned short int __pad2;
14#define _HAVE___PAD2
15 unsigned long int st_size;
16 unsigned long int st_blksize;
17 unsigned long int st_blocks;
18 struct timespec st_atim;
19 struct timespec st_mtim;
20 struct timespec st_ctim;
21 unsigned long int __glibc_reserved4;
22#define _HAVE___UNUSED4
23 unsigned long int __glibc_reserved5;
24#define _HAVE___UNUSED5
25 };
26
27#define _HAVE_STAT___UNUSED4
28#define _HAVE_STAT___UNUSED5
29#define _HAVE_STAT___PAD1
30#define _HAVE_STAT___PAD2
31#define _HAVE_STAT_NSEC
32#define _HAVE_STAT64___PAD1
33#define _HAVE_STAT64___PAD2
34#define _HAVE_STAT64___ST_INO
35#define _HAVE_STAT64_NSEC
36
37#define STAT_IS_KERNEL_STAT 0
38#define STAT64_IS_KERNEL_STAT64 1
39#define XSTAT_IS_XSTAT64 0
40#define STATFS_IS_STATFS64 0
lib/libc/glibc/sysdeps/unix/sysv/linux/kstat_cp.h deleted-2
...@@ -1,2 +0,0 @@
1/* Empty, it is overridden by an architecture which might require copy to or
2 from a kernel_stat stat struct to glibc export stat{64}. */
lib/libc/glibc/sysdeps/unix/sysv/linux/m68k/kernel_stat.h deleted-40
...@@ -1,40 +0,0 @@
1/* Definition of `struct stat' used in the kernel.. */
2struct kernel_stat
3 {
4 unsigned short int st_dev;
5 unsigned short int __pad1;
6#define _HAVE___PAD1
7 unsigned long int st_ino;
8 unsigned short int st_mode;
9 unsigned short int st_nlink;
10 unsigned short int st_uid;
11 unsigned short int st_gid;
12 unsigned short int st_rdev;
13 unsigned short int __pad2;
14#define _HAVE___PAD2
15 unsigned long int st_size;
16 unsigned long int st_blksize;
17 unsigned long int st_blocks;
18 struct timespec st_atim;
19 struct timespec st_mtim;
20 struct timespec st_ctim;
21 unsigned long int __glibc_reserved4;
22#define _HAVE___UNUSED4
23 unsigned long int __glibc_reserved5;
24#define _HAVE___UNUSED5
25 };
26
27#define _HAVE_STAT___UNUSED4
28#define _HAVE_STAT___UNUSED5
29#define _HAVE_STAT___PAD1
30#define _HAVE_STAT___PAD2
31#define _HAVE_STAT_NSEC
32#define _HAVE_STAT64___PAD1
33#define _HAVE_STAT64___PAD2
34#define _HAVE_STAT64___ST_INO
35#define _HAVE_STAT64_NSEC
36
37#define STAT_IS_KERNEL_STAT 0
38#define STAT64_IS_KERNEL_STAT64 1
39#define XSTAT_IS_XSTAT64 0
40#define STATFS_IS_STATFS64 0
lib/libc/glibc/sysdeps/unix/sysv/linux/mips/kernel_stat.h deleted-75
...@@ -1,75 +0,0 @@
1#ifndef _KERNEL_STAT_H
2#define _KERNEL_STAT_H
3
4#include <sgidefs.h>
5/* As tempting as it is to define XSTAT_IS_XSTAT64 for n64, the
6 userland data structures are not identical, because of different
7 padding. */
8/* Definition of `struct stat' used in the kernel. */
9#if _MIPS_SIM != _ABIO32
10struct kernel_stat
11 {
12 unsigned int st_dev;
13 unsigned int __pad1[3];
14 unsigned long long st_ino;
15 unsigned int st_mode;
16 unsigned int st_nlink;
17 int st_uid;
18 int st_gid;
19 unsigned int st_rdev;
20 unsigned int __pad2[3];
21 long long st_size;
22 unsigned int st_atime_sec;
23 unsigned int st_atime_nsec;
24 unsigned int st_mtime_sec;
25 unsigned int st_mtime_nsec;
26 unsigned int st_ctime_sec;
27 unsigned int st_ctime_nsec;
28 unsigned int st_blksize;
29 unsigned int __pad3;
30 unsigned long long st_blocks;
31 };
32#else
33struct kernel_stat
34 {
35 unsigned long int st_dev;
36 long int __pad1[3]; /* Reserved for network id */
37 unsigned long int st_ino;
38 unsigned long int st_mode;
39 unsigned long int st_nlink;
40 long int st_uid;
41 long int st_gid;
42 unsigned long int st_rdev;
43 long int __pad2[2];
44 long int st_size;
45 long int __pad3;
46 unsigned int st_atime_sec;
47 unsigned int st_atime_nsec;
48 unsigned int st_mtime_sec;
49 unsigned int st_mtime_nsec;
50 unsigned int st_ctime_sec;
51 unsigned int st_ctime_nsec;
52 long int st_blksize;
53 long int st_blocks;
54 char st_fstype[16]; /* Filesystem type name, unsupported */
55 long st_pad4[8];
56 /* Linux specific fields */
57 unsigned int st_flags;
58 unsigned int st_gen;
59 };
60#endif
61
62#define STAT_IS_KERNEL_STAT 0
63#define STAT64_IS_KERNEL_STAT64 0
64#define XSTAT_IS_XSTAT64 0
65#if _MIPS_SIM == _ABI64
66# define STATFS_IS_STATFS64 1
67#else
68# define STATFS_IS_STATFS64 0
69#endif
70/* MIPS64 has unsigned 32 bit timestamps fields, so use statx as well. */
71#if _MIPS_SIM == _ABI64
72# define STAT_HAS_TIME32
73#endif
74
75#endif
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/s390-32/kernel_stat.h deleted-40
...@@ -1,40 +0,0 @@
1/* Definition of `struct stat' used in the kernel.. */
2struct kernel_stat
3 {
4 unsigned short int st_dev;
5 unsigned short int __pad1;
6#define _HAVE___PAD1
7 unsigned long int st_ino;
8 unsigned short int st_mode;
9 unsigned short int st_nlink;
10 unsigned short int st_uid;
11 unsigned short int st_gid;
12 unsigned short int st_rdev;
13 unsigned short int __pad2;
14#define _HAVE___PAD2
15 unsigned long int st_size;
16 unsigned long int st_blksize;
17 unsigned long int st_blocks;
18 struct timespec st_atim;
19 struct timespec st_mtim;
20 struct timespec st_ctim;
21 unsigned long int __glibc_reserved4;
22#define _HAVE___UNUSED4
23 unsigned long int __glibc_reserved5;
24#define _HAVE___UNUSED5
25 };
26
27#define _HAVE_STAT___UNUSED4
28#define _HAVE_STAT___UNUSED5
29#define _HAVE_STAT___PAD1
30#define _HAVE_STAT___PAD2
31#define _HAVE_STAT_NSEC
32#define _HAVE_STAT64___PAD1
33#define _HAVE_STAT64___PAD2
34#define _HAVE_STAT64___ST_INO
35#define _HAVE_STAT64_NSEC
36
37#define STAT_IS_KERNEL_STAT 0
38#define STAT64_IS_KERNEL_STAT64 1
39#define XSTAT_IS_XSTAT64 0
40#define STATFS_IS_STATFS64 0
lib/libc/glibc/sysdeps/unix/sysv/linux/sh/kernel_stat.h deleted-40
...@@ -1,40 +0,0 @@
1/* Definition of `struct stat' used in the kernel.. */
2struct kernel_stat
3 {
4 unsigned short int st_dev;
5 unsigned short int __pad1;
6#define _HAVE___PAD1
7 unsigned long int st_ino;
8 unsigned short int st_mode;
9 unsigned short int st_nlink;
10 unsigned short int st_uid;
11 unsigned short int st_gid;
12 unsigned short int st_rdev;
13 unsigned short int __pad2;
14#define _HAVE___PAD2
15 unsigned long int st_size;
16 unsigned long int st_blksize;
17 unsigned long int st_blocks;
18 struct timespec st_atim;
19 struct timespec st_mtim;
20 struct timespec st_ctim;
21 unsigned long int __glibc_reserved4;
22#define _HAVE___UNUSED4
23 unsigned long int __glibc_reserved5;
24#define _HAVE___UNUSED5
25 };
26
27#define _HAVE_STAT___UNUSED4
28#define _HAVE_STAT___UNUSED5
29#define _HAVE_STAT___PAD1
30#define _HAVE_STAT___PAD2
31#define _HAVE_STAT_NSEC
32#define _HAVE_STAT64___PAD1
33#define _HAVE_STAT64___PAD2
34#define _HAVE_STAT64___ST_INO
35#define _HAVE_STAT64_NSEC
36
37#define STAT_IS_KERNEL_STAT 0
38#define STAT64_IS_KERNEL_STAT64 1
39#define XSTAT_IS_XSTAT64 0
40#define STATFS_IS_STATFS64 0
lib/libc/glibc/sysdeps/unix/sysv/linux/sparc/sparc32/kernel_stat.h deleted-37
...@@ -1,37 +0,0 @@
1/* Definition of `struct stat' used in the kernel */
2struct kernel_stat
3 {
4 unsigned short int st_dev;
5 unsigned long int st_ino;
6 unsigned short int st_mode;
7 short int st_nlink;
8 unsigned short int st_uid;
9 unsigned short int st_gid;
10 unsigned short int st_rdev;
11 long int st_size;
12 struct timespec st_atim;
13 struct timespec st_mtim;
14 struct timespec st_ctim;
15 long int st_blksize;
16 long int st_blocks;
17 unsigned long int __glibc_reserved4;
18 unsigned long int __glibc_reserved5;
19 };
20
21#define _HAVE___UNUSED4
22#define _HAVE___UNUSED5
23
24#define _HAVE_STAT___UNUSED4
25#define _HAVE_STAT___UNUSED5
26#define _HAVE_STAT___PAD1
27#define _HAVE_STAT___PAD2
28#define _HAVE_STAT64___UNUSED4
29#define _HAVE_STAT64___UNUSED5
30#define _HAVE_STAT64___PAD2
31#define _HAVE_STAT_NSEC
32#define _HAVE_STAT64_NSEC
33
34#define STAT_IS_KERNEL_STAT 0
35#define STAT64_IS_KERNEL_STAT64 1
36#define XSTAT_IS_XSTAT64 0
37#define STATFS_IS_STATFS64 0
lib/libc/glibc/sysdeps/unix/sysv/linux/sparc/sparc64/kernel_stat.h deleted-58
...@@ -1,58 +0,0 @@
1#ifndef _KERNEL_STAT_H
2#define _KERNEL_STAT_H
3
4/* Definition of `struct stat' used in the kernel */
5struct kernel_stat
6 {
7 unsigned int st_dev;
8 unsigned long int st_ino;
9 unsigned int st_mode;
10 short int st_nlink;
11 unsigned int st_uid;
12 unsigned int st_gid;
13 unsigned int st_rdev;
14 long int st_size;
15 long int st_atime_sec;
16 long int st_mtime_sec;
17 long int st_ctime_sec;
18 long int st_blksize;
19 long int st_blocks;
20 unsigned long int __glibc_reserved1;
21 unsigned long int __glibc_reserved2;
22 };
23
24/* Definition of `struct stat64' used in the kernel. */
25struct kernel_stat64
26 {
27 unsigned long int st_dev;
28 unsigned long int st_ino;
29 unsigned long int st_nlink;
30
31 unsigned int st_mode;
32 unsigned int st_uid;
33 unsigned int st_gid;
34 unsigned int __pad0;
35
36 unsigned long int st_rdev;
37 long int st_size;
38 long int st_blksize;
39 long int st_blocks;
40
41 unsigned long int st_atime_sec;
42 unsigned long int st_atime_nsec;
43 unsigned long int st_mtime_sec;
44 unsigned long int st_mtime_nsec;
45 unsigned long int st_ctime_sec;
46 unsigned long int st_ctime_nsec;
47 long int __glibc_reserved[3];
48 };
49
50#define STAT_IS_KERNEL_STAT 0
51#define STAT64_IS_KERNEL_STAT64 0
52#define XSTAT_IS_XSTAT64 1
53#ifdef __arch64__
54# define STATFS_IS_STATFS64 1
55#else
56# define STATFS_IS_STATFS64 0
57#endif
58#endif /* _KERNEL_STAT_H */
lib/libc/include/generic-glibc/string.h+6
...@@ -501,6 +501,11 @@ extern char *stpncpy (char *__restrict __dest,...@@ -501,6 +501,11 @@ extern char *stpncpy (char *__restrict __dest,
501 __THROW __nonnull ((1, 2));501 __THROW __nonnull ((1, 2));
502#endif502#endif
503503
504/*
505 * strlcpy and strlcat introduced in glibc 2.38
506 * https://sourceware.org/git/?p=glibc.git;a=commit;h=2e0bbbfbf95fc9e22692e93658a6fbdd2d4554da
507 */
508#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 38) || __GLIBC__ > 2
504#ifdef __USE_MISC509#ifdef __USE_MISC
505/* Copy at most N - 1 characters from SRC to DEST. */510/* Copy at most N - 1 characters from SRC to DEST. */
506extern size_t strlcpy (char *__restrict __dest,511extern size_t strlcpy (char *__restrict __dest,
...@@ -513,6 +518,7 @@ extern size_t strlcat (char *__restrict __dest,...@@ -513,6 +518,7 @@ extern size_t strlcat (char *__restrict __dest,
513 const char *__restrict __src, size_t __n)518 const char *__restrict __src, size_t __n)
514 __THROW __nonnull ((1, 2)) __attr_access ((__read_write__, 1, 3));519 __THROW __nonnull ((1, 2)) __attr_access ((__read_write__, 1, 3));
515#endif520#endif
521#endif /* glibc v2.38 and later */
516522
517#ifdef __USE_GNU523#ifdef __USE_GNU
518/* Compare S1 and S2 as strings holding name & indices/version numbers. */524/* Compare S1 and S2 as strings holding name & indices/version numbers. */
lib/std/fs/test.zig-3
...@@ -660,9 +660,6 @@ test "readAllAlloc" {...@@ -660,9 +660,6 @@ test "readAllAlloc" {
660}660}
661661
662test "Dir.statFile" {662test "Dir.statFile" {
663 // TODO: Re-enable once https://github.com/ziglang/zig/issues/17034 is solved
664 if (builtin.os.tag == .linux and builtin.link_libc and builtin.abi == .gnu) return error.SkipZigTest;
665
666 try testWithAllSupportedPathTypes(struct {663 try testWithAllSupportedPathTypes(struct {
667 fn impl(ctx: *TestContext) !void {664 fn impl(ctx: *TestContext) !void {
668 const test_file_name = try ctx.transformPath("test_file");665 const test_file_name = try ctx.transformPath("test_file");
src/glibc.zig+48-36
...@@ -20,7 +20,7 @@ pub const Lib = struct {...@@ -20,7 +20,7 @@ pub const Lib = struct {
20};20};
2121
22pub const ABI = struct {22pub const ABI = struct {
23 all_versions: []const Version,23 all_versions: []const Version, // all defined versions (one abilist from v2.0.0 up to current)
24 all_targets: []const target_util.ArchOsAbi,24 all_targets: []const target_util.ArchOsAbi,
25 /// The bytes from the file verbatim, starting from the u16 number25 /// The bytes from the file verbatim, starting from the u16 number
26 /// of function inclusions.26 /// of function inclusions.
...@@ -172,6 +172,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr...@@ -172,6 +172,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
172172
173 const target = comp.root_mod.resolved_target.result;173 const target = comp.root_mod.resolved_target.result;
174 const target_ver = target.os.version_range.linux.glibc;174 const target_ver = target.os.version_range.linux.glibc;
175 const nonshared_stat = target_ver.order(.{ .major = 2, .minor = 32, .patch = 0 }) != .gt;
175 const start_old_init_fini = target_ver.order(.{ .major = 2, .minor = 33, .patch = 0 }) != .gt;176 const start_old_init_fini = target_ver.order(.{ .major = 2, .minor = 33, .patch = 0 }) != .gt;
176177
177 // In all cases in this function, we add the C compiler flags to178 // In all cases in this function, we add the C compiler flags to
...@@ -276,54 +277,72 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr...@@ -276,54 +277,72 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
276 },277 },
277 .libc_nonshared_a => {278 .libc_nonshared_a => {
278 const s = path.sep_str;279 const s = path.sep_str;
279 const linux_prefix = lib_libc_glibc ++
280 "sysdeps" ++ s ++ "unix" ++ s ++ "sysv" ++ s ++ "linux" ++ s;
281 const Flavor = enum { nonshared, shared };
282 const Dep = struct {280 const Dep = struct {
283 path: []const u8,281 path: []const u8,
284 flavor: Flavor = .shared,282 include: bool = true,
285 exclude: bool = false,
286 };283 };
287 const deps = [_]Dep{284 const deps = [_]Dep{
285 .{ .path = lib_libc_glibc ++ "stdlib" ++ s ++ "atexit.c" },
286 .{ .path = lib_libc_glibc ++ "stdlib" ++ s ++ "at_quick_exit.c" },
287 .{ .path = lib_libc_glibc ++ "sysdeps" ++ s ++ "pthread" ++ s ++ "pthread_atfork.c" },
288 .{ .path = lib_libc_glibc ++ "debug" ++ s ++ "stack_chk_fail_local.c" },
289
290 // libc_nonshared.a redirected stat functions to xstat until glibc 2.33,
291 // when they were finally versioned like other symbols.
292 .{
293 .path = lib_libc_glibc ++ "io" ++ s ++ "stat-2.32.c",
294 .include = nonshared_stat,
295 },
296 .{
297 .path = lib_libc_glibc ++ "io" ++ s ++ "fstat-2.32.c",
298 .include = nonshared_stat,
299 },
300 .{
301 .path = lib_libc_glibc ++ "io" ++ s ++ "lstat-2.32.c",
302 .include = nonshared_stat,
303 },
288 .{304 .{
289 .path = lib_libc_glibc ++ "stdlib" ++ s ++ "atexit.c",305 .path = lib_libc_glibc ++ "io" ++ s ++ "stat64-2.32.c",
290 .flavor = .nonshared,306 .include = nonshared_stat,
291 },307 },
292 .{308 .{
293 .path = lib_libc_glibc ++ "stdlib" ++ s ++ "at_quick_exit.c",309 .path = lib_libc_glibc ++ "io" ++ s ++ "fstat64-2.32.c",
294 .flavor = .nonshared,310 .include = nonshared_stat,
295 },311 },
296 .{312 .{
297 .path = lib_libc_glibc ++ "sysdeps" ++ s ++ "pthread" ++ s ++ "pthread_atfork.c",313 .path = lib_libc_glibc ++ "io" ++ s ++ "lstat64-2.32.c",
298 .flavor = .nonshared,314 .include = nonshared_stat,
299 },315 },
300 .{316 .{
301 .path = lib_libc_glibc ++ "debug" ++ s ++ "stack_chk_fail_local.c",317 .path = lib_libc_glibc ++ "io" ++ s ++ "fstatat-2.32.c",
302 .flavor = .nonshared,318 .include = nonshared_stat,
303 },319 },
304 .{ .path = lib_libc_glibc ++ "csu" ++ s ++ "errno.c" },320 .{
321 .path = lib_libc_glibc ++ "io" ++ s ++ "fstatat64-2.32.c",
322 .include = nonshared_stat,
323 },
324 .{
325 .path = lib_libc_glibc ++ "io" ++ s ++ "mknodat-2.32.c",
326 .include = nonshared_stat,
327 },
328 .{
329 .path = lib_libc_glibc ++ "io" ++ s ++ "mknod-2.32.c",
330 .include = nonshared_stat,
331 },
332
333 // __libc_start_main used to require statically linked init/fini callbacks
334 // until glibc 2.34 when they were assimilated into the shared library.
305 .{335 .{
306 .path = lib_libc_glibc ++ "csu" ++ s ++ "elf-init-2.33.c",336 .path = lib_libc_glibc ++ "csu" ++ s ++ "elf-init-2.33.c",
307 .exclude = !start_old_init_fini,337 .include = start_old_init_fini,
308 },338 },
309 .{ .path = linux_prefix ++ "stat.c" },
310 .{ .path = linux_prefix ++ "fstat.c" },
311 .{ .path = linux_prefix ++ "lstat.c" },
312 .{ .path = linux_prefix ++ "stat64.c" },
313 .{ .path = linux_prefix ++ "fstat64.c" },
314 .{ .path = linux_prefix ++ "lstat64.c" },
315 .{ .path = linux_prefix ++ "fstatat.c" },
316 .{ .path = linux_prefix ++ "fstatat64.c" },
317 .{ .path = linux_prefix ++ "mknodat.c" },
318 .{ .path = lib_libc_glibc ++ "io" ++ s ++ "mknod.c" },
319 .{ .path = linux_prefix ++ "stat_t64_cp.c" },
320 };339 };
321340
322 var files_buf: [deps.len]Compilation.CSourceFile = undefined;341 var files_buf: [deps.len]Compilation.CSourceFile = undefined;
323 var files_index: usize = 0;342 var files_index: usize = 0;
324343
325 for (deps) |dep| {344 for (deps) |dep| {
326 if (dep.exclude) continue;345 if (!dep.include) continue;
327346
328 var args = std.ArrayList([]const u8).init(arena);347 var args = std.ArrayList([]const u8).init(arena);
329 try args.appendSlice(&[_][]const u8{348 try args.appendSlice(&[_][]const u8{
...@@ -347,13 +366,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr...@@ -347,13 +366,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
347 try args.append("-DCAN_USE_REGISTER_ASM_EBP");366 try args.append("-DCAN_USE_REGISTER_ASM_EBP");
348 }367 }
349368
350 const shared_def = switch (dep.flavor) {
351 .nonshared => "-DLIBC_NONSHARED=1",
352 // glibc passes `-DSHARED` for these. However, empirically if
353 // we do that here we will see undefined symbols such as `__GI_memcpy`.
354 // So we pass the same thing as for nonshared.
355 .shared => "-DLIBC_NONSHARED=1",
356 };
357 try args.appendSlice(&[_][]const u8{369 try args.appendSlice(&[_][]const u8{
358 "-D_LIBC_REENTRANT",370 "-D_LIBC_REENTRANT",
359 "-include",371 "-include",
...@@ -363,7 +375,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr...@@ -363,7 +375,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr
363 "-include",375 "-include",
364 try lib_path(comp, arena, lib_libc_glibc ++ "include" ++ path.sep_str ++ "libc-symbols.h"),376 try lib_path(comp, arena, lib_libc_glibc ++ "include" ++ path.sep_str ++ "libc-symbols.h"),
365 "-DPIC",377 "-DPIC",
366 shared_def,378 "-DLIBC_NONSHARED=1",
367 "-DTOP_NAMESPACE=glibc",379 "-DTOP_NAMESPACE=glibc",
368 });380 });
369 files_buf[files_index] = .{381 files_buf[files_index] = .{
src/print_targets.zig+6-3
...@@ -79,9 +79,12 @@ pub fn cmdTargets(...@@ -79,9 +79,12 @@ pub fn cmdTargets(
79 try jws.objectField("glibc");79 try jws.objectField("glibc");
80 try jws.beginArray();80 try jws.beginArray();
81 for (glibc_abi.all_versions) |ver| {81 for (glibc_abi.all_versions) |ver| {
82 const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver});82 // Actual glibc minimum is architecture specific. This just covers the broadest minimum.
83 defer allocator.free(tmp);83 if (ver.order(target.glibc_min_version) != .lt) {
84 try jws.write(tmp);84 const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver});
85 defer allocator.free(tmp);
86 try jws.write(tmp);
87 }
85 }88 }
86 try jws.endArray();89 try jws.endArray();
8790
src/target.zig+18-3
...@@ -11,10 +11,16 @@ pub const ArchOsAbi = struct {...@@ -11,10 +11,16 @@ pub const ArchOsAbi = struct {
11 os: std.Target.Os.Tag,11 os: std.Target.Os.Tag,
12 abi: std.Target.Abi,12 abi: std.Target.Abi,
13 os_ver: ?std.SemanticVersion = null,13 os_ver: ?std.SemanticVersion = null,
14
15 // Minimum glibc version that provides support for the arch/os (for
16 // .abi = .gnu). For most entries, the .glibc_min is null,
17 // meaning the Zig minimum required by the standard library (see
18 // glibc_min_version) is sufficient.
19 glibc_min: ?std.SemanticVersion = null,
14};20};
1521
16pub const available_libcs = [_]ArchOsAbi{22pub const available_libcs = [_]ArchOsAbi{
17 .{ .arch = .aarch64_be, .os = .linux, .abi = .gnu },23 .{ .arch = .aarch64_be, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 17, .patch = 0 } },
18 .{ .arch = .aarch64_be, .os = .linux, .abi = .musl },24 .{ .arch = .aarch64_be, .os = .linux, .abi = .musl },
19 .{ .arch = .aarch64_be, .os = .windows, .abi = .gnu },25 .{ .arch = .aarch64_be, .os = .windows, .abi = .gnu },
20 .{ .arch = .aarch64, .os = .linux, .abi = .gnu },26 .{ .arch = .aarch64, .os = .linux, .abi = .gnu },
...@@ -54,14 +60,14 @@ pub const available_libcs = [_]ArchOsAbi{...@@ -54,14 +60,14 @@ pub const available_libcs = [_]ArchOsAbi{
54 .{ .arch = .mips, .os = .linux, .abi = .gnueabi },60 .{ .arch = .mips, .os = .linux, .abi = .gnueabi },
55 .{ .arch = .mips, .os = .linux, .abi = .gnueabihf },61 .{ .arch = .mips, .os = .linux, .abi = .gnueabihf },
56 .{ .arch = .mips, .os = .linux, .abi = .musl },62 .{ .arch = .mips, .os = .linux, .abi = .musl },
57 .{ .arch = .powerpc64le, .os = .linux, .abi = .gnu },63 .{ .arch = .powerpc64le, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 19, .patch = 0 } },
58 .{ .arch = .powerpc64le, .os = .linux, .abi = .musl },64 .{ .arch = .powerpc64le, .os = .linux, .abi = .musl },
59 .{ .arch = .powerpc64, .os = .linux, .abi = .gnu },65 .{ .arch = .powerpc64, .os = .linux, .abi = .gnu },
60 .{ .arch = .powerpc64, .os = .linux, .abi = .musl },66 .{ .arch = .powerpc64, .os = .linux, .abi = .musl },
61 .{ .arch = .powerpc, .os = .linux, .abi = .gnueabi },67 .{ .arch = .powerpc, .os = .linux, .abi = .gnueabi },
62 .{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf },68 .{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf },
63 .{ .arch = .powerpc, .os = .linux, .abi = .musl },69 .{ .arch = .powerpc, .os = .linux, .abi = .musl },
64 .{ .arch = .riscv64, .os = .linux, .abi = .gnu },70 .{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },
65 .{ .arch = .riscv64, .os = .linux, .abi = .musl },71 .{ .arch = .riscv64, .os = .linux, .abi = .musl },
66 .{ .arch = .s390x, .os = .linux, .abi = .gnu },72 .{ .arch = .s390x, .os = .linux, .abi = .gnu },
67 .{ .arch = .s390x, .os = .linux, .abi = .musl },73 .{ .arch = .s390x, .os = .linux, .abi = .musl },
...@@ -76,6 +82,9 @@ pub const available_libcs = [_]ArchOsAbi{...@@ -76,6 +82,9 @@ pub const available_libcs = [_]ArchOsAbi{
76 .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 10, .minor = 7, .patch = 0 } },82 .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 10, .minor = 7, .patch = 0 } },
77};83};
7884
85/// Minimum glibc version, due to dependencies from the Zig standard library on glibc symbols
86pub const glibc_min_version: std.SemanticVersion = .{ .major = 2, .minor = 17, .patch = 0 };
87
79pub fn libCGenericName(target: std.Target) [:0]const u8 {88pub fn libCGenericName(target: std.Target) [:0]const u8 {
80 switch (target.os.tag) {89 switch (target.os.tag) {
81 .windows => return "mingw",90 .windows => return "mingw",
...@@ -154,6 +163,12 @@ pub fn canBuildLibC(target: std.Target) bool {...@@ -154,6 +163,12 @@ pub fn canBuildLibC(target: std.Target) bool {
154 const ver = target.os.version_range.semver;163 const ver = target.os.version_range.semver;
155 return ver.min.order(libc.os_ver.?) != .lt;164 return ver.min.order(libc.os_ver.?) != .lt;
156 }165 }
166 // Ensure glibc (aka *-linux-gnu) version is supported
167 if (target.isGnuLibC()) {
168 const min_glibc_ver = libc.glibc_min orelse glibc_min_version;
169 const target_glibc_ver = target.os.version_range.linux.glibc;
170 return target_glibc_ver.order(min_glibc_ver) != .lt;
171 }
157 return true;172 return true;
158 }173 }
159 }174 }
test/link/glibc_compat/build.zig+101
...@@ -1,4 +1,14 @@...@@ -1,4 +1,14 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
3
4// To run executables linked against a specific glibc version, the
5// run-time glibc version needs to be new enough. Check the host's glibc
6// version. Note that this does not allow for translation/vm/emulation
7// services to run these tests.
8const running_glibc_ver: ?std.SemanticVersion = switch (builtin.os.tag) {
9 .linux => builtin.os.version_range.linux.glibc,
10 else => null,
11};
212
3pub fn build(b: *std.Build) void {13pub fn build(b: *std.Build) void {
4 const test_step = b.step("test", "Test");14 const test_step = b.step("test", "Test");
...@@ -17,4 +27,95 @@ pub fn build(b: *std.Build) void {...@@ -17,4 +27,95 @@ pub fn build(b: *std.Build) void {
17 _ = exe.getEmittedBin();27 _ = exe.getEmittedBin();
18 test_step.dependOn(&exe.step);28 test_step.dependOn(&exe.step);
19 }29 }
30
31 // Build & run against a sampling of supported glibc versions
32 for ([_][]const u8{
33 "native-linux-gnu.2.17", // Currently oldest supported, see #17769
34 "native-linux-gnu.2.23",
35 "native-linux-gnu.2.28",
36 "native-linux-gnu.2.33",
37 "native-linux-gnu.2.38",
38 "native-linux-gnu",
39 }) |t| {
40 const target = b.resolveTargetQuery(std.Target.Query.parse(
41 .{ .arch_os_abi = t },
42 ) catch unreachable);
43
44 const glibc_ver = target.result.os.version_range.linux.glibc;
45
46 const exe = b.addExecutable(.{
47 .name = t,
48 .root_source_file = .{ .path = "glibc_runtime_check.zig" },
49 .target = target,
50 });
51 exe.linkLibC();
52
53 // Only try running the test if the host glibc is known to be good enough. Ideally, the Zig
54 // test runner would be able to check this, but see https://github.com/ziglang/zig/pull/17702#issuecomment-1831310453
55 if (running_glibc_ver) |running_ver| {
56 if (glibc_ver.order(running_ver) == .lt) {
57 const run_cmd = b.addRunArtifact(exe);
58 run_cmd.skip_foreign_checks = true;
59 run_cmd.expectExitCode(0);
60
61 test_step.dependOn(&run_cmd.step);
62 }
63 }
64 const check = exe.checkObject();
65
66 // __errno_location is always a dynamically linked symbol
67 check.checkInDynamicSymtab();
68 check.checkExact("0 0 UND FUNC GLOBAL DEFAULT __errno_location");
69
70 // before v2.32 fstatat redirects through __fxstatat, afterwards its a
71 // normal dynamic symbol
72 if (glibc_ver.order(.{ .major = 2, .minor = 32, .patch = 0 }) == .lt) {
73 check.checkInDynamicSymtab();
74 check.checkExact("0 0 UND FUNC GLOBAL DEFAULT __fxstatat");
75
76 check.checkInSymtab();
77 check.checkContains("FUNC LOCAL HIDDEN fstatat");
78 } else {
79 check.checkInDynamicSymtab();
80 check.checkExact("0 0 UND FUNC GLOBAL DEFAULT fstatat");
81
82 check.checkInSymtab();
83 check.checkNotPresent("FUNC LOCAL HIDDEN fstatat");
84 }
85
86 // before v2.26 reallocarray is not supported
87 if (glibc_ver.order(.{ .major = 2, .minor = 26, .patch = 0 }) == .lt) {
88 check.checkInDynamicSymtab();
89 check.checkNotPresent("reallocarray");
90 } else {
91 check.checkInDynamicSymtab();
92 check.checkExact("0 0 UND FUNC GLOBAL DEFAULT reallocarray");
93 }
94
95 // before v2.38 strlcpy is not supported
96 if (glibc_ver.order(.{ .major = 2, .minor = 38, .patch = 0 }) == .lt) {
97 check.checkInDynamicSymtab();
98 check.checkNotPresent("strlcpy");
99 } else {
100 check.checkInDynamicSymtab();
101 check.checkExact("0 0 UND FUNC GLOBAL DEFAULT strlcpy");
102 }
103
104 // v2.16 introduced getauxval(), so always present
105 check.checkInDynamicSymtab();
106 check.checkExact("0 0 UND FUNC GLOBAL DEFAULT getauxval");
107
108 // Always have a dynamic "exit" reference
109 check.checkInDynamicSymtab();
110 check.checkExact("0 0 UND FUNC GLOBAL DEFAULT exit");
111
112 // An atexit local symbol is defined, and depends on undefined dynamic
113 // __cxa_atexit.
114 check.checkInSymtab();
115 check.checkContains("FUNC LOCAL HIDDEN atexit");
116 check.checkInDynamicSymtab();
117 check.checkExact("0 0 UND FUNC GLOBAL DEFAULT __cxa_atexit");
118
119 test_step.dependOn(&check.step);
120 }
20}121}
test/link/glibc_compat/glibc_runtime_check.zig created+116
...@@ -0,0 +1,116 @@
1// A zig test case that exercises some glibc symbols that have uncovered
2// problems in the past. This test must be compiled against a glibc.
3//
4// The build.zig tests the binary built from this source to see that
5// symbols are statically or dynamically linked, as expected.
6
7const std = @import("std");
8const builtin = @import("builtin");
9const assert = std.debug.assert;
10
11const c_malloc = @cImport(
12 @cInclude("malloc.h"), // for reallocarray
13);
14
15const c_stdlib = @cImport(
16 @cInclude("stdlib.h"), // for atexit
17);
18
19const c_string = @cImport(
20 @cInclude("string.h"), // for strlcpy
21);
22
23// Version of glibc this test is being built to run against
24const glibc_ver = builtin.target.os.version_range.linux.glibc;
25
26// PR #17034 - fstat moved between libc_nonshared and libc
27fn checkStat() !void {
28 const cwdFd = std.fs.cwd().fd;
29
30 var stat = std.mem.zeroes(std.c.Stat);
31 var result = std.c.fstatat(cwdFd, "a_file_that_definitely_does_not_exist", &stat, 0);
32 assert(result == -1);
33 assert(std.c.getErrno(result) == .NOENT);
34
35 result = std.c.stat("a_file_that_definitely_does_not_exist", &stat);
36 assert(result == -1);
37 assert(std.c.getErrno(result) == .NOENT);
38}
39
40// PR #17607 - reallocarray not visible in headers
41fn checkReallocarray() !void {
42 // reallocarray was introduced in v2.26
43 if (comptime glibc_ver.order(.{ .major = 2, .minor = 26, .patch = 0 }) == .lt) {
44 if (@hasDecl(c_malloc, "reallocarray")) {
45 @compileError("Before v2.26 'malloc.h' does not define 'reallocarray'");
46 }
47 } else {
48 return try checkReallocarray_v2_26();
49 }
50}
51
52fn checkReallocarray_v2_26() !void {
53 const size = 16;
54 const tenX = c_malloc.reallocarray(c_malloc.NULL, 10, size);
55 const elevenX = c_malloc.reallocarray(tenX, 11, size);
56
57 assert(tenX != c_malloc.NULL);
58 assert(elevenX != c_malloc.NULL);
59}
60
61// getauxval introduced in v2.16
62fn checkGetAuxVal() !void {
63 if (comptime glibc_ver.order(.{ .major = 2, .minor = 16, .patch = 0 }) == .lt) {
64 if (@hasDecl(std.c, "getauxval")) {
65 @compileError("Before v2.16 glibc does not define 'getauxval'");
66 }
67 } else {
68 try checkGetAuxVal_v2_16();
69 }
70}
71
72fn checkGetAuxVal_v2_16() !void {
73 const base = std.c.getauxval(std.elf.AT_BASE);
74 const pgsz = std.c.getauxval(std.elf.AT_PAGESZ);
75
76 assert(base != 0);
77 assert(pgsz != 0);
78}
79
80// strlcpy introduced in v2.38, which is newer than many installed glibcs
81fn checkStrlcpy() !void {
82 if (comptime glibc_ver.order(.{ .major = 2, .minor = 38, .patch = 0 }) == .lt) {
83 if (@hasDecl(c_string, "strlcpy")) {
84 @compileError("Before v2.38 glibc does not define 'strlcpy'");
85 }
86 } else {
87 try checkStrlcpy_v2_38();
88 }
89}
90
91fn checkStrlcpy_v2_38() !void {
92 var buf: [99]u8 = undefined;
93 const used = c_string.strlcpy(&buf, "strlcpy works!", buf.len);
94 assert(used == 15);
95}
96
97// atexit is part of libc_nonshared, so ensure its linked in correctly
98fn forceExit0Callback() callconv(.C) void {
99 std.c.exit(0); // Override the main() exit code
100}
101
102fn checkAtExit() !void {
103 const result = c_stdlib.atexit(forceExit0Callback);
104 assert(result == 0);
105}
106
107pub fn main() !u8 {
108 try checkStat();
109 try checkReallocarray();
110 try checkStrlcpy();
111
112 try checkGetAuxVal();
113 try checkAtExit();
114
115 std.c.exit(1); // overridden by atexit() callback
116}