From 7dcf7412c474c28deee5deeb21f109096fd9ec9e Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Thu, 24 Aug 2023 18:26:27 +0900 Subject: [PATCH 01/10] glibc: get correct files compiled into libc_nonshared.a The scope of libc_nonshared.a was greatly changed in glibc 2.33 and 2.34, but only the change from 2.34 was reflected so far. Glibc 2.33 finally switched to versioned symbols for stat functions, meaning that libc_nonshared.a no longer contains them since 2.33. Relevant files were therefore reverted to 2.32 versions and renamed accordingly. This commit also removes errno.c, which was probably added to libc_nonshared.a based on a wrong assumption that glibc/include/errno.h requires glibc/csu/errno.c. In reality errno.h should refer to __libc_errno (not to be confused with the public __errno_location), which should be imported from libc.so. The inclusion of errno.c resulted in wrong compile options as well; this commit fixes them as well. Fixes #16152 --- lib/libc/glibc/io/fstat-2.32.c | 55 ++++++++++++++++++++ lib/libc/glibc/io/fstat64-2.32.c | 52 +++++++++++++++++++ lib/libc/glibc/io/fstatat-2.32.c | 52 +++++++++++++++++++ lib/libc/glibc/io/fstatat64-2.32.c | 52 +++++++++++++++++++ lib/libc/glibc/io/lstat-2.32.c | 55 ++++++++++++++++++++ lib/libc/glibc/io/lstat64-2.32.c | 52 +++++++++++++++++++ lib/libc/glibc/io/mknod-2.32.c | 55 ++++++++++++++++++++ lib/libc/glibc/io/mknodat-2.32.c | 53 +++++++++++++++++++ lib/libc/glibc/io/stat-2.32.c | 54 ++++++++++++++++++++ lib/libc/glibc/io/stat64-2.32.c | 52 +++++++++++++++++++ src/glibc.zig | 82 +++++++++++++++++------------- 11 files changed, 579 insertions(+), 35 deletions(-) create mode 100644 lib/libc/glibc/io/fstat-2.32.c create mode 100644 lib/libc/glibc/io/fstat64-2.32.c create mode 100644 lib/libc/glibc/io/fstatat-2.32.c create mode 100644 lib/libc/glibc/io/fstatat64-2.32.c create mode 100644 lib/libc/glibc/io/lstat-2.32.c create mode 100644 lib/libc/glibc/io/lstat64-2.32.c create mode 100644 lib/libc/glibc/io/mknod-2.32.c create mode 100644 lib/libc/glibc/io/mknodat-2.32.c create mode 100644 lib/libc/glibc/io/stat-2.32.c create mode 100644 lib/libc/glibc/io/stat64-2.32.c diff --git a/lib/libc/glibc/io/fstat-2.32.c b/lib/libc/glibc/io/fstat-2.32.c new file mode 100644 index 000000000000..6ce077dc4ae2 --- /dev/null +++ b/lib/libc/glibc/io/fstat-2.32.c @@ -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 + . */ + +#include + +/* This definition is only used if inlining fails for this function; see + the last page of . 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) diff --git a/lib/libc/glibc/io/fstat64-2.32.c b/lib/libc/glibc/io/fstat64-2.32.c new file mode 100644 index 000000000000..c4dd3acd6046 --- /dev/null +++ b/lib/libc/glibc/io/fstat64-2.32.c @@ -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 + . */ + +#include + +/* This definition is only used if inlining fails for this function; see + the last page of . 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); +} diff --git a/lib/libc/glibc/io/fstatat-2.32.c b/lib/libc/glibc/io/fstatat-2.32.c new file mode 100644 index 000000000000..edc773487abf --- /dev/null +++ b/lib/libc/glibc/io/fstatat-2.32.c @@ -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 + . */ + +#include + +/* This definition is only used if inlining fails for this function; see + the last page of . 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); +} diff --git a/lib/libc/glibc/io/fstatat64-2.32.c b/lib/libc/glibc/io/fstatat64-2.32.c new file mode 100644 index 000000000000..b57133bd9093 --- /dev/null +++ b/lib/libc/glibc/io/fstatat64-2.32.c @@ -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 + . */ + +#include + +/* This definition is only used if inlining fails for this function; see + the last page of . 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); +} diff --git a/lib/libc/glibc/io/lstat-2.32.c b/lib/libc/glibc/io/lstat-2.32.c new file mode 100644 index 000000000000..7134741106d7 --- /dev/null +++ b/lib/libc/glibc/io/lstat-2.32.c @@ -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 + . */ + +#include + +/* This definition is only used if inlining fails for this function; see + the last page of . 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) diff --git a/lib/libc/glibc/io/lstat64-2.32.c b/lib/libc/glibc/io/lstat64-2.32.c new file mode 100644 index 000000000000..a890da71a853 --- /dev/null +++ b/lib/libc/glibc/io/lstat64-2.32.c @@ -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 + . */ + +#include + +/* This definition is only used if inlining fails for this function; see + the last page of . 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 lstat64 +int +attribute_hidden +lstat64 (const char *file, struct stat64 *buf) +{ + return __lxstat64 (_STAT_VER, file, buf); +} diff --git a/lib/libc/glibc/io/mknod-2.32.c b/lib/libc/glibc/io/mknod-2.32.c new file mode 100644 index 000000000000..ac968292303d --- /dev/null +++ b/lib/libc/glibc/io/mknod-2.32.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1995-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 + . */ + + +#include +#include + +/* This definition is only used if inlining fails for this function; see + the last page of . 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. */ + +int +attribute_hidden +__mknod (const char *path, mode_t mode, dev_t dev) +{ + return __xmknod (_MKNOD_VER, path, mode, &dev); +} + +weak_hidden_alias (__mknod, mknod) diff --git a/lib/libc/glibc/io/mknodat-2.32.c b/lib/libc/glibc/io/mknodat-2.32.c new file mode 100644 index 000000000000..65c9f1aa9c2d --- /dev/null +++ b/lib/libc/glibc/io/mknodat-2.32.c @@ -0,0 +1,53 @@ +/* Copyright (C) 1995-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 + . */ + + +#include +#include + +/* This definition is only used if inlining fails for this function; see + the last page of . 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. */ + +int +attribute_hidden +mknodat (int fd, const char *path, mode_t mode, dev_t dev) +{ + return __xmknodat (_MKNOD_VER, fd, path, mode, &dev); +} diff --git a/lib/libc/glibc/io/stat-2.32.c b/lib/libc/glibc/io/stat-2.32.c new file mode 100644 index 000000000000..8c3cd877c8c3 --- /dev/null +++ b/lib/libc/glibc/io/stat-2.32.c @@ -0,0 +1,54 @@ +/* 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 + . */ + +#include + +/* This definition is only used if inlining fails for this function; see + the last page of . 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 stat +int +attribute_hidden +__stat (const char *file, struct stat *buf) +{ + return __xstat (_STAT_VER, file, buf); +} + +weak_hidden_alias (__stat, stat) diff --git a/lib/libc/glibc/io/stat64-2.32.c b/lib/libc/glibc/io/stat64-2.32.c new file mode 100644 index 000000000000..8b6b662f3ac4 --- /dev/null +++ b/lib/libc/glibc/io/stat64-2.32.c @@ -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 + . */ + +#include + +/* This definition is only used if inlining fails for this function; see + the last page of . 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 stat64 +int +attribute_hidden +stat64 (const char *file, struct stat64 *buf) +{ + return __xstat64 (_STAT_VER, file, buf); +} diff --git a/src/glibc.zig b/src/glibc.zig index 00d76f32fb0d..d4b617402115 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -172,6 +172,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr const target = comp.root_mod.resolved_target.result; const target_ver = target.os.version_range.linux.glibc; + const nonshared_stat = target_ver.order(.{ .major = 2, .minor = 32, .patch = 0 }) != .gt; const start_old_init_fini = target_ver.order(.{ .major = 2, .minor = 33, .patch = 0 }) != .gt; // 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 }, .libc_nonshared_a => { const s = path.sep_str; - const linux_prefix = lib_libc_glibc ++ - "sysdeps" ++ s ++ "unix" ++ s ++ "sysv" ++ s ++ "linux" ++ s; - const Flavor = enum { nonshared, shared }; const Dep = struct { path: []const u8, - flavor: Flavor = .shared, - exclude: bool = false, + include: bool = true, }; const deps = [_]Dep{ + .{ .path = lib_libc_glibc ++ "stdlib" ++ s ++ "atexit.c" }, + .{ .path = lib_libc_glibc ++ "stdlib" ++ s ++ "at_quick_exit.c" }, + .{ .path = lib_libc_glibc ++ "sysdeps" ++ s ++ "pthread" ++ s ++ "pthread_atfork.c" }, + .{ .path = lib_libc_glibc ++ "debug" ++ s ++ "stack_chk_fail_local.c" }, + + // libc_nonshared.a redirected stat functions to xstat until glibc 2.33, + // when they were finally versioned like other symbols. + .{ + .path = lib_libc_glibc ++ "io" ++ s ++ "stat-2.32.c", + .include = nonshared_stat, + }, + .{ + .path = lib_libc_glibc ++ "io" ++ s ++ "fstat-2.32.c", + .include = nonshared_stat, + }, + .{ + .path = lib_libc_glibc ++ "io" ++ s ++ "lstat-2.32.c", + .include = nonshared_stat, + }, .{ - .path = lib_libc_glibc ++ "stdlib" ++ s ++ "atexit.c", - .flavor = .nonshared, + .path = lib_libc_glibc ++ "io" ++ s ++ "stat64-2.32.c", + .include = nonshared_stat, }, .{ - .path = lib_libc_glibc ++ "stdlib" ++ s ++ "at_quick_exit.c", - .flavor = .nonshared, + .path = lib_libc_glibc ++ "io" ++ s ++ "fstat64-2.32.c", + .include = nonshared_stat, }, .{ - .path = lib_libc_glibc ++ "sysdeps" ++ s ++ "pthread" ++ s ++ "pthread_atfork.c", - .flavor = .nonshared, + .path = lib_libc_glibc ++ "io" ++ s ++ "lstat64-2.32.c", + .include = nonshared_stat, }, .{ - .path = lib_libc_glibc ++ "debug" ++ s ++ "stack_chk_fail_local.c", - .flavor = .nonshared, + .path = lib_libc_glibc ++ "io" ++ s ++ "fstatat-2.32.c", + .include = nonshared_stat, }, - .{ .path = lib_libc_glibc ++ "csu" ++ s ++ "errno.c" }, + .{ + .path = lib_libc_glibc ++ "io" ++ s ++ "fstatat64-2.32.c", + .include = nonshared_stat, + }, + .{ + .path = lib_libc_glibc ++ "io" ++ s ++ "mknodat-2.32.c", + .include = nonshared_stat, + }, + .{ + .path = lib_libc_glibc ++ "io" ++ s ++ "mknod-2.32.c", + .include = nonshared_stat, + }, + + // __libc_start_main used to require statically linked init/fini callbacks + // until glibc 2.34 when they were assimilated into the shared library. .{ .path = lib_libc_glibc ++ "csu" ++ s ++ "elf-init-2.33.c", - .exclude = !start_old_init_fini, + .include = start_old_init_fini, }, - .{ .path = linux_prefix ++ "stat.c" }, - .{ .path = linux_prefix ++ "fstat.c" }, - .{ .path = linux_prefix ++ "lstat.c" }, - .{ .path = linux_prefix ++ "stat64.c" }, - .{ .path = linux_prefix ++ "fstat64.c" }, - .{ .path = linux_prefix ++ "lstat64.c" }, - .{ .path = linux_prefix ++ "fstatat.c" }, - .{ .path = linux_prefix ++ "fstatat64.c" }, - .{ .path = linux_prefix ++ "mknodat.c" }, - .{ .path = lib_libc_glibc ++ "io" ++ s ++ "mknod.c" }, - .{ .path = linux_prefix ++ "stat_t64_cp.c" }, }; var files_buf: [deps.len]Compilation.CSourceFile = undefined; var files_index: usize = 0; for (deps) |dep| { - if (dep.exclude) continue; + if (!dep.include) continue; var args = std.ArrayList([]const u8).init(arena); try args.appendSlice(&[_][]const u8{ @@ -347,13 +366,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr try args.append("-DCAN_USE_REGISTER_ASM_EBP"); } - const shared_def = switch (dep.flavor) { - .nonshared => "-DLIBC_NONSHARED=1", - // glibc passes `-DSHARED` for these. However, empirically if - // we do that here we will see undefined symbols such as `__GI_memcpy`. - // So we pass the same thing as for nonshared. - .shared => "-DLIBC_NONSHARED=1", - }; try args.appendSlice(&[_][]const u8{ "-D_LIBC_REENTRANT", "-include", @@ -363,7 +375,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: *std.Progr "-include", try lib_path(comp, arena, lib_libc_glibc ++ "include" ++ path.sep_str ++ "libc-symbols.h"), "-DPIC", - shared_def, + "-DLIBC_NONSHARED=1", "-DTOP_NAMESPACE=glibc", }); files_buf[files_index] = .{ From f1bd218a884e7ddca2b6c43658eebf2747adb35b Mon Sep 17 00:00:00 2001 From: Kang Seonghoon Date: Thu, 24 Aug 2023 19:56:16 +0900 Subject: [PATCH 02/10] glibc: remove unused stat-related files for 2.33+ Effectively reverts 3dcd3612dca6f649a1e05f558c5d6ed462d2e4a4. --- .../unix/sysv/linux/alpha/kernel_stat.h | 91 ------------------- .../sysdeps/unix/sysv/linux/arm/kernel_stat.h | 40 -------- .../unix/sysv/linux/hppa/kernel_stat.h | 36 -------- .../unix/sysv/linux/i386/kernel_stat.h | 40 -------- .../glibc/sysdeps/unix/sysv/linux/kstat_cp.h | 2 - .../unix/sysv/linux/m68k/kernel_stat.h | 40 -------- .../unix/sysv/linux/mips/kernel_stat.h | 75 --------------- .../sysv/linux/s390/s390-32/kernel_stat.h | 40 -------- .../sysdeps/unix/sysv/linux/sh/kernel_stat.h | 40 -------- .../sysv/linux/sparc/sparc32/kernel_stat.h | 37 -------- .../sysv/linux/sparc/sparc64/kernel_stat.h | 58 ------------ 11 files changed, 499 deletions(-) delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/alpha/kernel_stat.h delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/arm/kernel_stat.h delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/hppa/kernel_stat.h delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/i386/kernel_stat.h delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/kstat_cp.h delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/m68k/kernel_stat.h delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/mips/kernel_stat.h delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/s390/s390-32/kernel_stat.h delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/sh/kernel_stat.h delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/sparc/sparc32/kernel_stat.h delete mode 100644 lib/libc/glibc/sysdeps/unix/sysv/linux/sparc/sparc64/kernel_stat.h diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/alpha/kernel_stat.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/alpha/kernel_stat.h deleted file mode 100644 index a292920969b2..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/alpha/kernel_stat.h +++ /dev/null @@ -1,91 +0,0 @@ -/* Definition of `struct stat' used in the kernel. */ -struct kernel_stat - { - unsigned int st_dev; - unsigned int st_ino; - unsigned int st_mode; - unsigned int st_nlink; - unsigned int st_uid; - unsigned int st_gid; - unsigned int st_rdev; - long int st_size; - unsigned long int st_atime_sec; - unsigned long int st_mtime_sec; - unsigned long int st_ctime_sec; - unsigned int st_blksize; - int st_blocks; - unsigned int st_flags; - unsigned int st_gen; - }; - -/* Definition of `struct stat64' used in the kernel. */ -struct kernel_stat64 - { - unsigned long st_dev; - unsigned long st_ino; - unsigned long st_rdev; - long st_size; - unsigned long st_blocks; - - unsigned int st_mode; - unsigned int st_uid; - unsigned int st_gid; - unsigned int st_blksize; - unsigned int st_nlink; - unsigned int __pad0; - - unsigned long st_atime_sec; - unsigned long st_atimensec; - unsigned long st_mtime_sec; - unsigned long st_mtimensec; - unsigned long st_ctime_sec; - unsigned long st_ctimensec; - long __glibc_reserved[3]; - }; - -/* Definition of `struct stat' used by glibc 2.0. */ -struct glibc2_stat - { - __dev_t st_dev; - __ino_t st_ino; - __mode_t st_mode; - __nlink_t st_nlink; - __uid_t st_uid; - __gid_t st_gid; - __dev_t st_rdev; - __off_t st_size; - __time_t st_atime_sec; - __time_t st_mtime_sec; - __time_t st_ctime_sec; - unsigned int st_blksize; - int st_blocks; - unsigned int st_flags; - unsigned int st_gen; - }; - -/* Definition of `struct stat' used by glibc 2.1. */ -struct glibc21_stat - { - __dev_t st_dev; - __ino64_t st_ino; - __mode_t st_mode; - __nlink_t st_nlink; - __uid_t st_uid; - __gid_t st_gid; - __dev_t st_rdev; - __off_t st_size; - __time_t st_atime_sec; - __time_t st_mtime_sec; - __time_t st_ctime_sec; - __blkcnt64_t st_blocks; - __blksize_t st_blksize; - unsigned int st_flags; - unsigned int st_gen; - int __pad3; - long __glibc_reserved[4]; - }; - -#define STAT_IS_KERNEL_STAT 0 -#define STAT64_IS_KERNEL_STAT64 1 -#define XSTAT_IS_XSTAT64 1 -#define STATFS_IS_STATFS64 0 diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/arm/kernel_stat.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/arm/kernel_stat.h deleted file mode 100644 index b1bc1459f08e..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/arm/kernel_stat.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Definition of `struct stat' used in the kernel.. */ -struct kernel_stat - { - unsigned short int st_dev; - unsigned short int __pad1; -#define _HAVE___PAD1 - unsigned long int st_ino; - unsigned short int st_mode; - unsigned short int st_nlink; - unsigned short int st_uid; - unsigned short int st_gid; - unsigned short int st_rdev; - unsigned short int __pad2; -#define _HAVE___PAD2 - unsigned long int st_size; - unsigned long int st_blksize; - unsigned long int st_blocks; - struct timespec st_atim; - struct timespec st_mtim; - struct timespec st_ctim; - unsigned long int __glibc_reserved4; -#define _HAVE___UNUSED4 - unsigned long int __glibc_reserved5; -#define _HAVE___UNUSED5 - }; - -#define _HAVE_STAT___UNUSED4 -#define _HAVE_STAT___UNUSED5 -#define _HAVE_STAT___PAD1 -#define _HAVE_STAT___PAD2 -#define _HAVE_STAT_NSEC -#define _HAVE_STAT64___PAD1 -#define _HAVE_STAT64___PAD2 -#define _HAVE_STAT64___ST_INO -#define _HAVE_STAT64_NSEC - -#define STAT_IS_KERNEL_STAT 0 -#define STAT64_IS_KERNEL_STAT64 1 -#define XSTAT_IS_XSTAT64 0 -#define STATFS_IS_STATFS64 0 diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/hppa/kernel_stat.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/hppa/kernel_stat.h deleted file mode 100644 index e8ad135e7023..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/hppa/kernel_stat.h +++ /dev/null @@ -1,36 +0,0 @@ -/* definition of "struct stat" from the kernel */ -struct kernel_stat { - unsigned long st_dev; /* dev_t is 32 bits on parisc */ - unsigned long st_ino; /* 32 bits */ - unsigned short st_mode; /* 16 bits */ - unsigned short st_nlink; /* 16 bits */ - unsigned short st_reserved1; /* old st_uid */ - unsigned short st_reserved2; /* old st_gid */ - unsigned long st_rdev; - unsigned long st_size; - struct timespec st_atim; - struct timespec st_mtim; - struct timespec st_ctim; - long st_blksize; - long st_blocks; - unsigned long __glibc_reserved1; /* ACL stuff */ - unsigned long __glibc_reserved2; /* network */ - unsigned long __glibc_reserved3; /* network */ - unsigned long __glibc_reserved4; /* cnodes */ - unsigned short __glibc_reserved5; /* netsite */ - short st_fstype; - unsigned long st_realdev; - unsigned short st_basemode; - unsigned short st_spareshort; - unsigned long st_uid; - unsigned long st_gid; - unsigned long st_spare4[3]; -}; - -#define _HAVE_STAT_NSEC -#define _HAVE_STAT64_NSEC - -#define STAT_IS_KERNEL_STAT 0 -#define STAT64_IS_KERNEL_STAT64 1 -#define XSTAT_IS_XSTAT64 0 -#define STATFS_IS_STATFS64 0 diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/i386/kernel_stat.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/i386/kernel_stat.h deleted file mode 100644 index b1bc1459f08e..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/i386/kernel_stat.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Definition of `struct stat' used in the kernel.. */ -struct kernel_stat - { - unsigned short int st_dev; - unsigned short int __pad1; -#define _HAVE___PAD1 - unsigned long int st_ino; - unsigned short int st_mode; - unsigned short int st_nlink; - unsigned short int st_uid; - unsigned short int st_gid; - unsigned short int st_rdev; - unsigned short int __pad2; -#define _HAVE___PAD2 - unsigned long int st_size; - unsigned long int st_blksize; - unsigned long int st_blocks; - struct timespec st_atim; - struct timespec st_mtim; - struct timespec st_ctim; - unsigned long int __glibc_reserved4; -#define _HAVE___UNUSED4 - unsigned long int __glibc_reserved5; -#define _HAVE___UNUSED5 - }; - -#define _HAVE_STAT___UNUSED4 -#define _HAVE_STAT___UNUSED5 -#define _HAVE_STAT___PAD1 -#define _HAVE_STAT___PAD2 -#define _HAVE_STAT_NSEC -#define _HAVE_STAT64___PAD1 -#define _HAVE_STAT64___PAD2 -#define _HAVE_STAT64___ST_INO -#define _HAVE_STAT64_NSEC - -#define STAT_IS_KERNEL_STAT 0 -#define STAT64_IS_KERNEL_STAT64 1 -#define XSTAT_IS_XSTAT64 0 -#define STATFS_IS_STATFS64 0 diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/kstat_cp.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/kstat_cp.h deleted file mode 100644 index 69397db0d2ee..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/kstat_cp.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Empty, it is overridden by an architecture which might require copy to or - from a kernel_stat stat struct to glibc export stat{64}. */ diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/m68k/kernel_stat.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/m68k/kernel_stat.h deleted file mode 100644 index b1bc1459f08e..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/m68k/kernel_stat.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Definition of `struct stat' used in the kernel.. */ -struct kernel_stat - { - unsigned short int st_dev; - unsigned short int __pad1; -#define _HAVE___PAD1 - unsigned long int st_ino; - unsigned short int st_mode; - unsigned short int st_nlink; - unsigned short int st_uid; - unsigned short int st_gid; - unsigned short int st_rdev; - unsigned short int __pad2; -#define _HAVE___PAD2 - unsigned long int st_size; - unsigned long int st_blksize; - unsigned long int st_blocks; - struct timespec st_atim; - struct timespec st_mtim; - struct timespec st_ctim; - unsigned long int __glibc_reserved4; -#define _HAVE___UNUSED4 - unsigned long int __glibc_reserved5; -#define _HAVE___UNUSED5 - }; - -#define _HAVE_STAT___UNUSED4 -#define _HAVE_STAT___UNUSED5 -#define _HAVE_STAT___PAD1 -#define _HAVE_STAT___PAD2 -#define _HAVE_STAT_NSEC -#define _HAVE_STAT64___PAD1 -#define _HAVE_STAT64___PAD2 -#define _HAVE_STAT64___ST_INO -#define _HAVE_STAT64_NSEC - -#define STAT_IS_KERNEL_STAT 0 -#define STAT64_IS_KERNEL_STAT64 1 -#define XSTAT_IS_XSTAT64 0 -#define STATFS_IS_STATFS64 0 diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/mips/kernel_stat.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/mips/kernel_stat.h deleted file mode 100644 index 19524f7ea442..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/mips/kernel_stat.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef _KERNEL_STAT_H -#define _KERNEL_STAT_H - -#include -/* As tempting as it is to define XSTAT_IS_XSTAT64 for n64, the - userland data structures are not identical, because of different - padding. */ -/* Definition of `struct stat' used in the kernel. */ -#if _MIPS_SIM != _ABIO32 -struct kernel_stat - { - unsigned int st_dev; - unsigned int __pad1[3]; - unsigned long long st_ino; - unsigned int st_mode; - unsigned int st_nlink; - int st_uid; - int st_gid; - unsigned int st_rdev; - unsigned int __pad2[3]; - long long st_size; - unsigned int st_atime_sec; - unsigned int st_atime_nsec; - unsigned int st_mtime_sec; - unsigned int st_mtime_nsec; - unsigned int st_ctime_sec; - unsigned int st_ctime_nsec; - unsigned int st_blksize; - unsigned int __pad3; - unsigned long long st_blocks; - }; -#else -struct kernel_stat - { - unsigned long int st_dev; - long int __pad1[3]; /* Reserved for network id */ - unsigned long int st_ino; - unsigned long int st_mode; - unsigned long int st_nlink; - long int st_uid; - long int st_gid; - unsigned long int st_rdev; - long int __pad2[2]; - long int st_size; - long int __pad3; - unsigned int st_atime_sec; - unsigned int st_atime_nsec; - unsigned int st_mtime_sec; - unsigned int st_mtime_nsec; - unsigned int st_ctime_sec; - unsigned int st_ctime_nsec; - long int st_blksize; - long int st_blocks; - char st_fstype[16]; /* Filesystem type name, unsupported */ - long st_pad4[8]; - /* Linux specific fields */ - unsigned int st_flags; - unsigned int st_gen; - }; -#endif - -#define STAT_IS_KERNEL_STAT 0 -#define STAT64_IS_KERNEL_STAT64 0 -#define XSTAT_IS_XSTAT64 0 -#if _MIPS_SIM == _ABI64 -# define STATFS_IS_STATFS64 1 -#else -# define STATFS_IS_STATFS64 0 -#endif -/* MIPS64 has unsigned 32 bit timestamps fields, so use statx as well. */ -#if _MIPS_SIM == _ABI64 -# define STAT_HAS_TIME32 -#endif - -#endif diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/s390-32/kernel_stat.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/s390-32/kernel_stat.h deleted file mode 100644 index b1bc1459f08e..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/s390/s390-32/kernel_stat.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Definition of `struct stat' used in the kernel.. */ -struct kernel_stat - { - unsigned short int st_dev; - unsigned short int __pad1; -#define _HAVE___PAD1 - unsigned long int st_ino; - unsigned short int st_mode; - unsigned short int st_nlink; - unsigned short int st_uid; - unsigned short int st_gid; - unsigned short int st_rdev; - unsigned short int __pad2; -#define _HAVE___PAD2 - unsigned long int st_size; - unsigned long int st_blksize; - unsigned long int st_blocks; - struct timespec st_atim; - struct timespec st_mtim; - struct timespec st_ctim; - unsigned long int __glibc_reserved4; -#define _HAVE___UNUSED4 - unsigned long int __glibc_reserved5; -#define _HAVE___UNUSED5 - }; - -#define _HAVE_STAT___UNUSED4 -#define _HAVE_STAT___UNUSED5 -#define _HAVE_STAT___PAD1 -#define _HAVE_STAT___PAD2 -#define _HAVE_STAT_NSEC -#define _HAVE_STAT64___PAD1 -#define _HAVE_STAT64___PAD2 -#define _HAVE_STAT64___ST_INO -#define _HAVE_STAT64_NSEC - -#define STAT_IS_KERNEL_STAT 0 -#define STAT64_IS_KERNEL_STAT64 1 -#define XSTAT_IS_XSTAT64 0 -#define STATFS_IS_STATFS64 0 diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/sh/kernel_stat.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/sh/kernel_stat.h deleted file mode 100644 index b1bc1459f08e..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/sh/kernel_stat.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Definition of `struct stat' used in the kernel.. */ -struct kernel_stat - { - unsigned short int st_dev; - unsigned short int __pad1; -#define _HAVE___PAD1 - unsigned long int st_ino; - unsigned short int st_mode; - unsigned short int st_nlink; - unsigned short int st_uid; - unsigned short int st_gid; - unsigned short int st_rdev; - unsigned short int __pad2; -#define _HAVE___PAD2 - unsigned long int st_size; - unsigned long int st_blksize; - unsigned long int st_blocks; - struct timespec st_atim; - struct timespec st_mtim; - struct timespec st_ctim; - unsigned long int __glibc_reserved4; -#define _HAVE___UNUSED4 - unsigned long int __glibc_reserved5; -#define _HAVE___UNUSED5 - }; - -#define _HAVE_STAT___UNUSED4 -#define _HAVE_STAT___UNUSED5 -#define _HAVE_STAT___PAD1 -#define _HAVE_STAT___PAD2 -#define _HAVE_STAT_NSEC -#define _HAVE_STAT64___PAD1 -#define _HAVE_STAT64___PAD2 -#define _HAVE_STAT64___ST_INO -#define _HAVE_STAT64_NSEC - -#define STAT_IS_KERNEL_STAT 0 -#define STAT64_IS_KERNEL_STAT64 1 -#define XSTAT_IS_XSTAT64 0 -#define STATFS_IS_STATFS64 0 diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/sparc/sparc32/kernel_stat.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/sparc/sparc32/kernel_stat.h deleted file mode 100644 index 4a2df42d375e..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/sparc/sparc32/kernel_stat.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Definition of `struct stat' used in the kernel */ -struct kernel_stat - { - unsigned short int st_dev; - unsigned long int st_ino; - unsigned short int st_mode; - short int st_nlink; - unsigned short int st_uid; - unsigned short int st_gid; - unsigned short int st_rdev; - long int st_size; - struct timespec st_atim; - struct timespec st_mtim; - struct timespec st_ctim; - long int st_blksize; - long int st_blocks; - unsigned long int __glibc_reserved4; - unsigned long int __glibc_reserved5; - }; - -#define _HAVE___UNUSED4 -#define _HAVE___UNUSED5 - -#define _HAVE_STAT___UNUSED4 -#define _HAVE_STAT___UNUSED5 -#define _HAVE_STAT___PAD1 -#define _HAVE_STAT___PAD2 -#define _HAVE_STAT64___UNUSED4 -#define _HAVE_STAT64___UNUSED5 -#define _HAVE_STAT64___PAD2 -#define _HAVE_STAT_NSEC -#define _HAVE_STAT64_NSEC - -#define STAT_IS_KERNEL_STAT 0 -#define STAT64_IS_KERNEL_STAT64 1 -#define XSTAT_IS_XSTAT64 0 -#define STATFS_IS_STATFS64 0 diff --git a/lib/libc/glibc/sysdeps/unix/sysv/linux/sparc/sparc64/kernel_stat.h b/lib/libc/glibc/sysdeps/unix/sysv/linux/sparc/sparc64/kernel_stat.h deleted file mode 100644 index 29d18908da92..000000000000 --- a/lib/libc/glibc/sysdeps/unix/sysv/linux/sparc/sparc64/kernel_stat.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _KERNEL_STAT_H -#define _KERNEL_STAT_H - -/* Definition of `struct stat' used in the kernel */ -struct kernel_stat - { - unsigned int st_dev; - unsigned long int st_ino; - unsigned int st_mode; - short int st_nlink; - unsigned int st_uid; - unsigned int st_gid; - unsigned int st_rdev; - long int st_size; - long int st_atime_sec; - long int st_mtime_sec; - long int st_ctime_sec; - long int st_blksize; - long int st_blocks; - unsigned long int __glibc_reserved1; - unsigned long int __glibc_reserved2; - }; - -/* Definition of `struct stat64' used in the kernel. */ -struct kernel_stat64 - { - unsigned long int st_dev; - unsigned long int st_ino; - unsigned long int st_nlink; - - unsigned int st_mode; - unsigned int st_uid; - unsigned int st_gid; - unsigned int __pad0; - - unsigned long int st_rdev; - long int st_size; - long int st_blksize; - long int st_blocks; - - unsigned long int st_atime_sec; - unsigned long int st_atime_nsec; - unsigned long int st_mtime_sec; - unsigned long int st_mtime_nsec; - unsigned long int st_ctime_sec; - unsigned long int st_ctime_nsec; - long int __glibc_reserved[3]; - }; - -#define STAT_IS_KERNEL_STAT 0 -#define STAT64_IS_KERNEL_STAT64 0 -#define XSTAT_IS_XSTAT64 1 -#ifdef __arch64__ -# define STATFS_IS_STATFS64 1 -#else -# define STATFS_IS_STATFS64 0 -#endif -#endif /* _KERNEL_STAT_H */ From 2c6372a11741cee93057fe15b002735e488b7dc9 Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Sun, 22 Oct 2023 23:02:24 -0700 Subject: [PATCH 03/10] glibc: restore "weak_hidden_alias" macro for older glibc versions The fstat,lstat,stat,mknod stubs used to build older (before v2.33) glibc versions depend on the weak_hidden_alias macro. It was removed from the glibc libc-symbols header, so patch it back in for the older builds. --- lib/libc/glibc/include/libc-symbols.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/libc/glibc/include/libc-symbols.h b/lib/libc/glibc/include/libc-symbols.h index 57946144888f..d684c9621482 100644 --- a/lib/libc/glibc/include/libc-symbols.h +++ b/lib/libc/glibc/include/libc-symbols.h @@ -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) From 1564cb0ab978b904e612a056c013bce8d6663a1b Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Mon, 23 Oct 2023 15:23:19 -0700 Subject: [PATCH 04/10] std/fs/test.zig: Remove work-around for stat() failures on glibc glibc variants now support the stat-family of calls correctly, so this test is safe to include. --- lib/std/fs/test.zig | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index 95cacd25d1f2..cd50b8aae883 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -660,9 +660,6 @@ test "readAllAlloc" { } test "Dir.statFile" { - // TODO: Re-enable once https://github.com/ziglang/zig/issues/17034 is solved - if (builtin.os.tag == .linux and builtin.link_libc and builtin.abi == .gnu) return error.SkipZigTest; - try testWithAllSupportedPathTypes(struct { fn impl(ctx: *TestContext) !void { const test_file_name = try ctx.transformPath("test_file"); From 42d7b69d8130bd3dba05dd75e671fcbf07177930 Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Tue, 24 Oct 2023 21:44:55 -0700 Subject: [PATCH 05/10] test/link/glibc_compat: test various older glibc versions Compile, link and run a test case against various glibc versions. Exercise symbols that have been probelmatic in the past. --- test/link/glibc_compat/build.zig | 95 +++++++++++++++++++ .../link/glibc_compat/glibc_runtime_check.zig | 94 ++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 test/link/glibc_compat/glibc_runtime_check.zig diff --git a/test/link/glibc_compat/build.zig b/test/link/glibc_compat/build.zig index bb8d5d056daf..cb2a906c2cb7 100644 --- a/test/link/glibc_compat/build.zig +++ b/test/link/glibc_compat/build.zig @@ -1,4 +1,14 @@ const std = @import("std"); +const builtin = @import("builtin"); + +// To run executables linked against a specific glibc version, the +// run-time glibc version needs to be new enough. Check the host's glibc +// version. Note that this does not allow for translation/vm/emulation +// services to run these tests. +const running_glibc_ver: ?std.SemanticVersion = switch (builtin.os.tag) { + .linux => builtin.os.version_range.linux.glibc, + else => null, +}; pub fn build(b: *std.Build) void { const test_step = b.step("test", "Test"); @@ -17,4 +27,89 @@ pub fn build(b: *std.Build) void { _ = exe.getEmittedBin(); test_step.dependOn(&exe.step); } + + // Build & run against a sampling of supported glibc versions + for ([_][]const u8{ + "native-linux-gnu.2.17", // Currently oldest supported, see #17769 + "native-linux-gnu.2.23", + "native-linux-gnu.2.28", + "native-linux-gnu.2.33", + "native-linux-gnu.2.38", + "native-linux-gnu", + }) |t| { + const target = b.resolveTargetQuery(std.Target.Query.parse( + .{ .arch_os_abi = t }, + ) catch unreachable); + + const glibc_ver = target.result.os.version_range.linux.glibc; + + const exe = b.addExecutable(.{ + .name = t, + .root_source_file = .{ .path = "glibc_runtime_check.zig" }, + .target = target, + }); + exe.linkLibC(); + + // Only try running the test if the host glibc is known to be good enough. Ideally, the Zig + // test runner would be able to check this, but see https://github.com/ziglang/zig/pull/17702#issuecomment-1831310453 + if (running_glibc_ver) |running_ver| { + if (glibc_ver.order(running_ver) == .lt) { + const run_cmd = b.addRunArtifact(exe); + run_cmd.skip_foreign_checks = true; + run_cmd.expectExitCode(0); + + test_step.dependOn(&run_cmd.step); + } + } + const check = exe.checkObject(); + + // __errno_location is always a dynamically linked symbol + check.checkInDynamicSymtab(); + check.checkExact("0 0 UND FUNC GLOBAL DEFAULT __errno_location"); + + // before v2.32 fstatat redirects through __fxstatat, afterwards its a + // normal dynamic symbol + if (glibc_ver.order(.{ .major = 2, .minor = 32, .patch = 0 }) == .lt) { + check.checkInDynamicSymtab(); + check.checkExact("0 0 UND FUNC GLOBAL DEFAULT __fxstatat"); + + check.checkInSymtab(); + check.checkContains("FUNC LOCAL HIDDEN fstatat"); + } else { + check.checkInDynamicSymtab(); + check.checkExact("0 0 UND FUNC GLOBAL DEFAULT fstatat"); + + check.checkInSymtab(); + check.checkNotPresent("FUNC LOCAL HIDDEN fstatat"); + } + + // before v2.26 reallocarray is not supported + if (glibc_ver.order(.{ .major = 2, .minor = 26, .patch = 0 }) == .lt) { + check.checkInDynamicSymtab(); + check.checkNotPresent("reallocarray"); + } else { + check.checkInDynamicSymtab(); + check.checkExact("0 0 UND FUNC GLOBAL DEFAULT reallocarray"); + } else { + check.checkInDynamicSymtab(); + check.checkNotPresent("reallocarray"); + } + + // v2.16 introduced getauxval(), so always present + check.checkInDynamicSymtab(); + check.checkExact("0 0 UND FUNC GLOBAL DEFAULT getauxval"); + + // Always have a dynamic "exit" reference + check.checkInDynamicSymtab(); + check.checkExact("0 0 UND FUNC GLOBAL DEFAULT exit"); + + // An atexit local symbol is defined, and depends on undefined dynamic + // __cxa_atexit. + check.checkInSymtab(); + check.checkContains("FUNC LOCAL HIDDEN atexit"); + check.checkInDynamicSymtab(); + check.checkExact("0 0 UND FUNC GLOBAL DEFAULT __cxa_atexit"); + + test_step.dependOn(&check.step); + } } diff --git a/test/link/glibc_compat/glibc_runtime_check.zig b/test/link/glibc_compat/glibc_runtime_check.zig new file mode 100644 index 000000000000..2866fefc67ad --- /dev/null +++ b/test/link/glibc_compat/glibc_runtime_check.zig @@ -0,0 +1,94 @@ +// A zig test case that exercises some glibc symbols that have uncovered +// problems in the past. This test must be compiled against a glibc. +// +// The build.zig tests the binary built from this source to see that +// symbols are statically or dynamically linked, as expected. + +const std = @import("std"); +const builtin = @import("builtin"); +const assert = std.debug.assert; + +const c_malloc = @cImport( + @cInclude("malloc.h"), // for reallocarray +); + +const c_stdlib = @cImport( + @cInclude("stdlib.h"), // for atexit +); + +// Version of glibc this test is being built to run against +const glibc_ver = builtin.target.os.version_range.linux.glibc; + +// PR #17034 - fstat moved between libc_nonshared and libc +fn checkStat() !void { + const cwdFd = std.fs.cwd().fd; + + var stat = std.mem.zeroes(std.c.Stat); + var result = std.c.fstatat(cwdFd, "a_file_that_definitely_does_not_exist", &stat, 0); + assert(result == -1); + assert(std.c.getErrno(result) == .NOENT); + + result = std.c.stat("a_file_that_definitely_does_not_exist", &stat); + assert(result == -1); + assert(std.c.getErrno(result) == .NOENT); +} + +// PR #17607 - reallocarray not visible in headers +fn checkReallocarray() !void { + // reallocarray was introduced in v2.26 + if (comptime glibc_ver.order(.{ .major = 2, .minor = 26, .patch = 0 }) == .lt) { + if (@hasDecl(c_malloc, "reallocarray")) { + @compileError("Before v2.26 'malloc.h' does not define 'reallocarray'"); + } + } else { + return try checkReallocarray_v2_26(); + } +} + +fn checkReallocarray_v2_26() !void { + const size = 16; + const tenX = c_malloc.reallocarray(c_malloc.NULL, 10, size); + const elevenX = c_malloc.reallocarray(tenX, 11, size); + + assert(tenX != c_malloc.NULL); + assert(elevenX != c_malloc.NULL); +} + +// getauxval introduced in v2.16 +fn checkGetAuxVal() !void { + if (comptime glibc_ver.order(.{ .major = 2, .minor = 16, .patch = 0 }) == .lt) { + if (@hasDecl(std.c, "getauxval")) { + @compileError("Before v2.16 glibc does not define 'getauxval'"); + } + } else { + try checkGetAuxVal_v2_16(); + } +} + +fn checkGetAuxVal_v2_16() !void { + const base = std.c.getauxval(std.elf.AT_BASE); + const pgsz = std.c.getauxval(std.elf.AT_PAGESZ); + + assert(base != 0); + assert(pgsz != 0); +} + +// atexit is part of libc_nonshared, so ensure its linked in correctly +fn forceExit0Callback() callconv(.C) void { + std.c.exit(0); // Override the main() exit code +} + +fn checkAtExit() !void { + const result = c_stdlib.atexit(forceExit0Callback); + assert(result == 0); +} + +pub fn main() !u8 { + try checkStat(); + try checkReallocarray(); + + try checkGetAuxVal(); + try checkAtExit(); + + std.c.exit(1); // overridden by atexit() callback +} From 71e809852c34a5a75f86829a188028ec12bbd4ec Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Mon, 23 Oct 2023 20:10:05 -0700 Subject: [PATCH 06/10] lib/libc/glibc/: Add README.md Add a README with an overview of how Zig's glibc support is implemented. --- lib/libc/glibc/README.md | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 lib/libc/glibc/README.md diff --git a/lib/libc/glibc/README.md b/lib/libc/glibc/README.md new file mode 100644 index 000000000000..f75356896842 --- /dev/null +++ b/lib/libc/glibc/README.md @@ -0,0 +1,85 @@ +# Zig GNU C Library ("glibc") Support + +*Date*: November, 2023 + +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 compilation +target 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 supports 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 +compliation 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). From c22d1c00a8825f60e7b01b97c6f73cbc21ca8257 Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Sun, 29 Oct 2023 14:38:48 -0700 Subject: [PATCH 07/10] src/target: Restrict usable glibc versions At a minimum required glibc is v2.17, as earlier versions do not define some symbols (e.g., getauxval()) used by the Zig standard library. Additionally, glibc only supports some architectures at more recent versions (e.g., riscv64 support came in glibc v2.27). So add a `glibc_min` field to `available_libcs` for architectures with stronger version requirements. Extend the existing `canBuildLibC` function to check the target against the Zig minimum, and the architecture/os minimum. Also filter the list shown by `zig targets`, too: $ zig targets | jq -c '.glibc' ["2.17.0","2.18.0","2.19.0","2.20.0","2.21.0","2.22.0","2.23.0","2.24.0","2.25.0","2.26.0","2.27.0","2.28.0","2.29.0","2.30.0","2.31.0","2.32.0","2.33.0","2.34.0","2.35.0","2.36.0","2.37.0","2.38.0"] Fixes #17034 Fixes #17769 --- src/glibc.zig | 2 +- src/print_targets.zig | 9 ++++++--- src/target.zig | 21 ++++++++++++++++++--- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/glibc.zig b/src/glibc.zig index d4b617402115..b7483b7012fd 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -20,7 +20,7 @@ pub const Lib = struct { }; pub const ABI = struct { - all_versions: []const Version, + all_versions: []const Version, // all defined versions (one abilist from v2.0.0 up to current) all_targets: []const target_util.ArchOsAbi, /// The bytes from the file verbatim, starting from the u16 number /// of function inclusions. diff --git a/src/print_targets.zig b/src/print_targets.zig index bfb2ac017702..f8390a03b921 100644 --- a/src/print_targets.zig +++ b/src/print_targets.zig @@ -79,9 +79,12 @@ pub fn cmdTargets( try jws.objectField("glibc"); try jws.beginArray(); for (glibc_abi.all_versions) |ver| { - const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver}); - defer allocator.free(tmp); - try jws.write(tmp); + // Actual glibc minimum is architecture specific. This just covers the broadest minimum. + if (ver.order(target.glibc_min_version) != .lt) { + const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver}); + defer allocator.free(tmp); + try jws.write(tmp); + } } try jws.endArray(); diff --git a/src/target.zig b/src/target.zig index 5ae5c420c2e3..acfa08903408 100644 --- a/src/target.zig +++ b/src/target.zig @@ -11,10 +11,16 @@ pub const ArchOsAbi = struct { os: std.Target.Os.Tag, abi: std.Target.Abi, os_ver: ?std.SemanticVersion = null, + + // Minimum glibc version that provides support for the arch/os (for + // .abi = .gnu). For most entries, the .glibc_min is null, + // meaning the Zig minimum required by the standard library (see + // glibc_min_version) is sufficient. + glibc_min: ?std.SemanticVersion = null, }; pub const available_libcs = [_]ArchOsAbi{ - .{ .arch = .aarch64_be, .os = .linux, .abi = .gnu }, + .{ .arch = .aarch64_be, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 17, .patch = 0 } }, .{ .arch = .aarch64_be, .os = .linux, .abi = .musl }, .{ .arch = .aarch64_be, .os = .windows, .abi = .gnu }, .{ .arch = .aarch64, .os = .linux, .abi = .gnu }, @@ -54,14 +60,14 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .mips, .os = .linux, .abi = .gnueabi }, .{ .arch = .mips, .os = .linux, .abi = .gnueabihf }, .{ .arch = .mips, .os = .linux, .abi = .musl }, - .{ .arch = .powerpc64le, .os = .linux, .abi = .gnu }, + .{ .arch = .powerpc64le, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 19, .patch = 0 } }, .{ .arch = .powerpc64le, .os = .linux, .abi = .musl }, .{ .arch = .powerpc64, .os = .linux, .abi = .gnu }, .{ .arch = .powerpc64, .os = .linux, .abi = .musl }, .{ .arch = .powerpc, .os = .linux, .abi = .gnueabi }, .{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf }, .{ .arch = .powerpc, .os = .linux, .abi = .musl }, - .{ .arch = .riscv64, .os = .linux, .abi = .gnu }, + .{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } }, .{ .arch = .riscv64, .os = .linux, .abi = .musl }, .{ .arch = .s390x, .os = .linux, .abi = .gnu }, .{ .arch = .s390x, .os = .linux, .abi = .musl }, @@ -76,6 +82,9 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .x86_64, .os = .macos, .abi = .none, .os_ver = .{ .major = 10, .minor = 7, .patch = 0 } }, }; +/// Minimum glibc version, due to dependencies from the Zig standard library on glibc symbols +pub const glibc_min_version: std.SemanticVersion = .{ .major = 2, .minor = 17, .patch = 0 }; + pub fn libCGenericName(target: std.Target) [:0]const u8 { switch (target.os.tag) { .windows => return "mingw", @@ -154,6 +163,12 @@ pub fn canBuildLibC(target: std.Target) bool { const ver = target.os.version_range.semver; return ver.min.order(libc.os_ver.?) != .lt; } + // Ensure glibc (aka *-linux-gnu) version is supported + if ((target.os.tag == .linux) and target.abi.isGnu()) { + const min_glibc_ver = libc.glibc_min orelse glibc_min_version; + const target_glibc_ver = target.os.version_range.linux.glibc; + return target_glibc_ver.order(min_glibc_ver) != .lt; + } return true; } } From 4a5d73a34d6473a6970d6aaa31703cfa43135729 Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Tue, 28 Nov 2023 19:55:35 -0800 Subject: [PATCH 08/10] glibc: strlcpy and strlcat arrived in glibc 2.38 So only expose these in generic-glibc/string.h if Zig is building a v2.38 (or later) glibc stub. Announcement of 2.38 that notes strlcpy and strlcat: https://lists.gnu.org/archive/html/info-gnu/2023-07/msg00010.html --- lib/libc/include/generic-glibc/string.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/libc/include/generic-glibc/string.h b/lib/libc/include/generic-glibc/string.h index 77b6aa346b51..353754d0c477 100644 --- a/lib/libc/include/generic-glibc/string.h +++ b/lib/libc/include/generic-glibc/string.h @@ -501,6 +501,11 @@ extern char *stpncpy (char *__restrict __dest, __THROW __nonnull ((1, 2)); #endif +/* + * strlcpy and strlcat introduced in glibc 2.38 + * https://sourceware.org/git/?p=glibc.git;a=commit;h=2e0bbbfbf95fc9e22692e93658a6fbdd2d4554da + */ +#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 38) || __GLIBC__ > 2 #ifdef __USE_MISC /* Copy at most N - 1 characters from SRC to DEST. */ extern size_t strlcpy (char *__restrict __dest, @@ -513,6 +518,7 @@ extern size_t strlcat (char *__restrict __dest, const char *__restrict __src, size_t __n) __THROW __nonnull ((1, 2)) __attr_access ((__read_write__, 1, 3)); #endif +#endif /* glibc v2.38 and later */ #ifdef __USE_GNU /* Compare S1 and S2 as strings holding name & indices/version numbers. */ From cbaaf6477fa314257a550515886563d6e7a06fc7 Mon Sep 17 00:00:00 2001 From: Pat Tullmann Date: Tue, 28 Nov 2023 20:26:17 -0800 Subject: [PATCH 09/10] test glibc_runtime_check: add strlcpy() check The strlcpy symbol was added in v2.38, so this is a handy symbol for creating binaries that won't run on relatively modern systems (e.g., mine, that has glibc 2.36 installed). --- test/link/glibc_compat/build.zig | 8 ++++++- .../link/glibc_compat/glibc_runtime_check.zig | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/test/link/glibc_compat/build.zig b/test/link/glibc_compat/build.zig index cb2a906c2cb7..e0cc1a70d81f 100644 --- a/test/link/glibc_compat/build.zig +++ b/test/link/glibc_compat/build.zig @@ -90,9 +90,15 @@ pub fn build(b: *std.Build) void { } else { check.checkInDynamicSymtab(); check.checkExact("0 0 UND FUNC GLOBAL DEFAULT reallocarray"); + } + + // before v2.38 strlcpy is not supported + if (glibc_ver.order(.{ .major = 2, .minor = 38, .patch = 0 }) == .lt) { + check.checkInDynamicSymtab(); + check.checkNotPresent("strlcpy"); } else { check.checkInDynamicSymtab(); - check.checkNotPresent("reallocarray"); + check.checkExact("0 0 UND FUNC GLOBAL DEFAULT strlcpy"); } // v2.16 introduced getauxval(), so always present diff --git a/test/link/glibc_compat/glibc_runtime_check.zig b/test/link/glibc_compat/glibc_runtime_check.zig index 2866fefc67ad..7344bafc6ed2 100644 --- a/test/link/glibc_compat/glibc_runtime_check.zig +++ b/test/link/glibc_compat/glibc_runtime_check.zig @@ -16,6 +16,10 @@ const c_stdlib = @cImport( @cInclude("stdlib.h"), // for atexit ); +const c_string = @cImport( + @cInclude("string.h"), // for strlcpy +); + // Version of glibc this test is being built to run against const glibc_ver = builtin.target.os.version_range.linux.glibc; @@ -73,6 +77,23 @@ fn checkGetAuxVal_v2_16() !void { assert(pgsz != 0); } +// strlcpy introduced in v2.38, which is newer than many installed glibcs +fn checkStrlcpy() !void { + if (comptime glibc_ver.order(.{ .major = 2, .minor = 38, .patch = 0 }) == .lt) { + if (@hasDecl(c_string, "strlcpy")) { + @compileError("Before v2.38 glibc does not define 'strlcpy'"); + } + } else { + try checkStrlcpy_v2_38(); + } +} + +fn checkStrlcpy_v2_38() !void { + var buf: [99]u8 = undefined; + const used = c_string.strlcpy(&buf, "strlcpy works!", buf.len); + assert(used == 15); +} + // atexit is part of libc_nonshared, so ensure its linked in correctly fn forceExit0Callback() callconv(.C) void { std.c.exit(0); // Override the main() exit code @@ -86,6 +107,7 @@ fn checkAtExit() !void { pub fn main() !u8 { try checkStat(); try checkReallocarray(); + try checkStrlcpy(); try checkGetAuxVal(); try checkAtExit(); From 362460ec24d802e6fba7f45ddff5f969642839df Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 4 Jan 2024 17:26:06 -0700 Subject: [PATCH 10/10] minor cosmetic fixups * fix typos and redundancies in docs * use Target.isGnuLibc --- lib/libc/glibc/README.md | 12 +++++------- src/target.zig | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/libc/glibc/README.md b/lib/libc/glibc/README.md index f75356896842..0bcf23ae343d 100644 --- a/lib/libc/glibc/README.md +++ b/lib/libc/glibc/README.md @@ -1,15 +1,13 @@ # Zig GNU C Library ("glibc") Support -*Date*: November, 2023 - 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 compilation -target defines which C library: `musl` for the -[musl C library](https://musl.libc.org/) or `gnu` for the GNU C library. +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 @@ -30,7 +28,7 @@ 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 supports Linux. +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. @@ -58,7 +56,7 @@ 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 -compliation across a variety of target C library versions. +compilation across a variety of target C library versions. ## Glibc static C-Runtime object files and libraries diff --git a/src/target.zig b/src/target.zig index acfa08903408..8c66017e79fc 100644 --- a/src/target.zig +++ b/src/target.zig @@ -164,7 +164,7 @@ pub fn canBuildLibC(target: std.Target) bool { return ver.min.order(libc.os_ver.?) != .lt; } // Ensure glibc (aka *-linux-gnu) version is supported - if ((target.os.tag == .linux) and target.abi.isGnu()) { + if (target.isGnuLibC()) { const min_glibc_ver = libc.glibc_min orelse glibc_min_version; const target_glibc_ver = target.os.version_range.linux.glibc; return target_glibc_ver.order(min_glibc_ver) != .lt;