Skip to content

Commit 166196a

Browse files
committed
fix(glibc).old
1 parent c288764 commit 166196a

3 files changed

Lines changed: 206 additions & 74 deletions

File tree

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include <stdarg.h>
2+
#include <fcntl.h>
3+
#include <unistd.h>
4+
#include <errno.h>
5+
#include <sysdep.h>
6+
#include <abort-instr.h>
7+
8+
#ifndef ABORT_INSTRUCTION
9+
# define ABORT_INSTRUCTION
10+
#endif
11+
12+
#if RTLD_PRIVATE_ERRNO
13+
int rtld_errno attribute_hidden;
14+
#endif
15+
16+
int __open (const char *file, int oflag, ...) attribute_hidden;
17+
int __close (int fd) attribute_hidden;
18+
int __access (const char *file, int type) attribute_hidden;
19+
void __libc_check_standard_fds (void) attribute_hidden;
20+
21+
int
22+
__open (const char *file, int oflag, ...)
23+
{
24+
mode_t mode = 0;
25+
26+
if (oflag & O_CREAT)
27+
{
28+
va_list arg;
29+
va_start (arg, oflag);
30+
mode = va_arg (arg, mode_t);
31+
va_end (arg);
32+
}
33+
34+
return INLINE_SYSCALL (open, 3, file, oflag, mode);
35+
}
36+
37+
int
38+
__close (int fd)
39+
{
40+
return INLINE_SYSCALL (close, 1, fd);
41+
}
42+
43+
int
44+
__access (const char *file, int type)
45+
{
46+
return INLINE_SYSCALL (access, 2, file, type);
47+
}
48+
49+
static void
50+
check_one_fd (int fd, int mode)
51+
{
52+
if (INLINE_SYSCALL (fcntl, 3, fd, F_GETFD, 0) == -1
53+
&& errno == EBADF)
54+
{
55+
const char *name;
56+
57+
if ((mode & O_ACCMODE) == O_WRONLY)
58+
name = "/dev/full";
59+
else
60+
name = "/dev/null";
61+
62+
int nullfd = __open (name, mode, 0);
63+
if (nullfd != fd)
64+
while (1)
65+
ABORT_INSTRUCTION;
66+
}
67+
}
68+
69+
void
70+
__libc_check_standard_fds (void)
71+
{
72+
#ifndef O_NOFOLLOW
73+
# define O_NOFOLLOW 0
74+
#endif
75+
check_one_fd (STDIN_FILENO, O_WRONLY | O_NOFOLLOW);
76+
check_one_fd (STDOUT_FILENO, O_RDONLY | O_NOFOLLOW);
77+
check_one_fd (STDERR_FILENO, O_RDONLY | O_NOFOLLOW);
78+
}

projects/gnu.org/glibc/package.yml

Lines changed: 124 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,20 @@ versions:
99
- /glibc-/
1010
- /\.tar\.xz/
1111

12-
# Empirically verified host-independent build (pkgx toolchain only,
13-
# debian:bookworm-slim base with no apt-installed compiler):
14-
# linux/x86-64: 2.17, 2.24, 2.27, 2.28, 2.34, 2.38, 2.41, 2.42, 2.43
15-
# linux/aarch64: 2.17, 2.24, 2.27, 2.28, 2.34, 2.38, 2.41, 2.42, 2.43
16-
# Full 9-version parity on both arches. Each bottle cross-tested on
17-
# Alpine 3.18 (musl host), Debian 11, Ubuntu 22.04 — all return
18-
# gnu_get_libc_version() = <bottle-version>.
12+
# Current support targets:
13+
# linux/x86-64: 2.17+
14+
# linux/aarch64: 2.28+
1915
#
20-
# 2.17 (manylinux2014 / CentOS 7 / HPC baseline) and 2.24
21-
# (manylinux_2_24) are built via a bootstrap-cascaded toolchain
22-
# (gcc 7.5 + binutils 2.28). The cascade procedure is documented in
23-
# README.md "HPC bootstrap cascade". The toolchain bottles produced
24-
# (gcc 9.5, gcc 7.5, binutils 2.28/2.30/2.31/2.32) are candidates
25-
# to ship in dist.pkgx.dev as `gnu.org/gcc` and `gnu.org/binutils`
26-
# older-version bottles — currently built inside the build env.
16+
# Older aarch64 glibc releases fail in rtld/ld.so with non-PIC relocation
17+
# errors under the modern pkgx toolchain. Treat <2.28 aarch64 as unsupported
18+
# unless/until we add a real old-toolchain bootstrap path.
2719
#
2820
# darwin/* is intentionally absent. glibc is the GNU C library for the
2921
# Linux kernel — macOS uses libSystem + dyld with an entirely separate
3022
# binary format (Mach-O vs ELF). There is no glibc port to Darwin and
3123
# bottling one would not produce something usable.
3224
platforms:
33-
- linux/x86-64
34-
- linux/aarch64
25+
- linux
3526

3627
build:
3728
# Skip brewkit's "SLOW rpath fixes" — it writes a 46-package
@@ -47,7 +38,10 @@ build:
4738
dependencies:
4839
gnu.org/make: ">=4.0"
4940
gnu.org/gawk: ">=3"
50-
gnu.org/gcc: "*" # pkgx ships 10.5–16.1; verified with 16.1
41+
gnu.org/gcc: 14 # gcc 16 trips old glibc aarch64 rtld / inline semantics
42+
gnu.org/gmp: ">=4.2"
43+
gnu.org/mpfr: ">=2.4.0"
44+
gnu.org/mpc: ">=0.8.0"
5145
gnu.org/binutils: ">=2.40" # required by glibc 2.42+; older glibcs also build with 2.46
5246
gnu.org/gettext: "*"
5347
gnu.org/texinfo: "*" # required for `make install` (manual/libc.info)
@@ -62,11 +56,17 @@ build:
6256
perl.org: "^5"
6357
python.org: "~3.11"
6458
kernel.org/linux-headers: "*" # the file that makes the build host-independent
65-
nixos.org/patchelf: "*" # used to detect ELF tools before wrapping them
6659

6760
working-directory: build
6861

6962
script:
63+
- run:
64+
- if test "{{hw.arch}}" = "aarch64"; then
65+
- echo "glibc {{version}} is unsupported on linux/aarch64; this recipe supports linux/aarch64 from 2.28 onward."
66+
- exit 1
67+
- fi
68+
if: <2.28
69+
7070
# Hygiene patches from nixpkgs. They prevent the new ld.so from reading
7171
# the host's /etc/ld.so.cache and /etc/ld.so.preload — both files have
7272
# glibc-version-specific binary formats, reading them with a different
@@ -82,51 +82,102 @@ build:
8282
if: ">=2.32"
8383
working-directory: ..
8484

85-
# glibc 2.17/2.18 configure has a python regex that rejects `make` >= 4.0.
86-
# 1-line fix preserving the same regex shape, accepting modern make.
87-
# Use # as sed delimiter because the pattern itself contains |.
88-
- run: sed -i 's#3\.79\* | 3\.\[89\]\*#3.79* | 3.[89]* | [4-9].* | [1-9][0-9]*#' configure
85+
- run:
86+
# glibc 2.17/2.18 configure has a version case that rejects `make` >= 4.0.
87+
# Keep the same case-pattern shape, accepting modern make.
88+
# Use # as sed delimiter because the pattern itself contains |.
89+
- sed -i 's#3\.79\* | 3\.\[89\]\*#3.79* | 3.[89]* | [4-9].* | [1-9][0-9]*#' configure
90+
# glibc 2.17/2.18 configure similarly only accepts gcc 4.x or 5–9.x.
91+
# Modern pkgx gcc is 10+, so extend the existing case branch.
92+
- sed -i 's#\[5-9\]\.\* )#[5-9].* | [1-9][0-9]*.* )#' configure
93+
# The ld --no-whole-archive probe uses pre-C99 function definitions
94+
# (`_start () {}`), but glibc itself still needs gnu99 later. Keep
95+
# gnu89 scoped to this configure probe; do not put it in CFLAGS.
96+
- sed -i '/checking for ld --no-whole-archive/,/-nostdlib/s/\$CFLAGS \$CPPFLAGS/\$CFLAGS -std=gnu89 \$CPPFLAGS/' configure
97+
# Force the configure cache so Makeconfig gets `gnu89-inline-CFLAGS=-fgnu89-inline`.
98+
- export libc_cv_gnu89_inline=yes
99+
# Likewise, stdio lock cleanup macros require `exceptions=-fexceptions`.
100+
- export libc_cv_gcc_exceptions=yes
101+
# With current GCC/binutils, glibc 2.17's rtld link keeps explicit
102+
# references to a few libc-private syscall wrappers that older builds
103+
# used to fold away. Keep this scoped to rtld so normal libc remains
104+
# upstream-shaped.
105+
- rm -f build/elf/dl-pkgx-rtld-compat.* build/elf/dl-allobjs.os build/elf/librtld* build/elf/ld.so build/elf/ld-linux*
106+
- install -m 644 props/dl-pkgx-rtld-compat-2.17.c sysdeps/unix/sysv/linux/dl-pkgx-rtld-compat.c
107+
- grep -q 'dl-pkgx-rtld-compat' sysdeps/unix/sysv/linux/Makefile ||
108+
sed -i 's/dl-fxstatat64/dl-fxstatat64 dl-pkgx-rtld-compat/' sysdeps/unix/sysv/linux/Makefile
109+
- awk -f $PROP sysdeps/unix/sysv/linux/Makefile > sysdeps/unix/sysv/linux/Makefile.pkgx
110+
- mv sysdeps/unix/sysv/linux/Makefile.pkgx sysdeps/unix/sysv/linux/Makefile
111+
- cat props/sysdeps-Makefile >> sysdeps/unix/sysv/linux/Makefile
112+
# glibc 2.17's early Makerules pass can evaluate before soversions.mk is
113+
# included, clearing `static-only-routines` and omitting elf-init.oS from
114+
# libc_nonshared.a. Dynamic build tools then fail to resolve
115+
# __libc_csu_init/fini from crt1.o.
116+
- sed -i '/ifndef libc.so-version/,/endif/s/^static-only-routines =/# static-only-routines =/' Makerules
117+
# Ensure the nonshared archive actually carries the csu entry points used
118+
# by crt1.o. crt1.o needs __libc_csu_init/fini from elf-init.oS, and this
119+
# old release's generated stamp handling is fragile enough to pin directly.
120+
- grep -q '^o-objects.oS += elf-init.oS$' csu/Makefile || echo 'o-objects.oS += elf-init.oS' >> csu/Makefile
121+
prop: |
122+
/# rtld-pkgx-alias-routines/ { skip = 1; next }
123+
skip && /^ifeq \(\$\(subdir\),elf\)$/ { next }
124+
skip && /^sysdep-rtld-routines \+=/ { next }
125+
skip && /^endif$/ { skip = 0; next }
126+
{ print }
89127
if: <2.19
90128
working-directory: ..
91129

92-
# glibc < 2.32 has multiple tentative .bss definitions of __nss_*_database
93-
# that gcc 10+'s default -fno-common rejects. Add -fcommon for old glibc.
94130
- run:
95-
- EXTRA_CFLAGS=""
96-
- if [ {{version.major}}{{version.minor}} -lt 232 ]; then
97-
- EXTRA_CFLAGS="-fcommon -Wno-error"
98-
- fi
131+
# glibc 2.24's Makerules try to copy <cstdlib>/<cmath> by deriving their
132+
# paths from `$(CXX) -M`; with modern C++ headers that probe can return
133+
# empty, making `install $< $@T` call install with no source operand.
134+
# Disable this optional workaround for the 2.24 build.
135+
- sed -i 's/^ifneq (,$(CXX))/ifneq (,$(CXX_DISABLED_FOR_PKGX))/' Makerules
99136
# glibc decides its own pie/-shared per target — pkgx gcc 16
100137
# is built with --enable-default-pie, so its CC defaults add
101138
# -fPIE/-pie. That breaks glibc's static auxiliary tools
102139
# (support/test-run-command et al) with "_DYNAMIC isn't
103140
# defined". Explicitly disable the default with -fno-PIE and
104141
# -no-pie at the link step; glibc adds them back per-target
105142
# where actually wanted (shared libs use -fPIC anyway).
106-
#
107-
# libc_cv_slibdir / libc_cv_rtlddir override the autoconf-cached
108-
# slibdir / rtlddir vars so libc.so.6 + ld-linux*.so go into
109-
# the sub-libdir alongside our other libs. Without this,
110-
# --libdir alone only affects gconv/audit plugins; libc.so.6
111-
# still ends up at $prefix/lib/ and pollutes consumers'
112-
# LD_LIBRARY_PATH (incompatible with the host's older ld-linux).
113-
- LIBDIR="{{prefix}}/lib/glibc-{{version.marketing}}"
114-
- CFLAGS="-O2 -fPIC $EXTRA_CFLAGS"
115-
libc_cv_slibdir="$LIBDIR"
116-
libc_cv_rtlddir="$LIBDIR"
117-
libc_cv_complocaledir="$LIBDIR/locale"
118-
libc_cv_static_pie=no
119-
../configure $ARGS
143+
- EXTRA_CFLAGS="$EXTRA_CFLAGS -fno-PIE"
144+
- LDFLAGS="$LDFLAGS -no-pie"
145+
if: <2.25
146+
working-directory: ..
120147

121-
- make --jobs {{ hw.concurrency }} CFLAGS-regexp.c=-fno-common
148+
# glibc < 2.32 has multiple tentative .bss definitions of __nss_*_database
149+
# that gcc 10+'s default -fno-common rejects. Add -fcommon for old glibc.
150+
- run: EXTRA_CFLAGS="$EXTRA_CFLAGS -fcommon -Wno-error"
151+
if: <2.32
152+
153+
# libc_cv_slibdir / libc_cv_rtlddir override the autoconf-cached
154+
# slibdir / rtlddir vars so libc.so.6 + ld-linux*.so go into
155+
# the sub-libdir alongside our other libs. Without this,
156+
# --libdir alone only affects gconv/audit plugins; libc.so.6
157+
# still ends up at $prefix/lib/ and pollutes consumers'
158+
# LD_LIBRARY_PATH (incompatible with the host's older ld-linux).
159+
- LIBDIR="{{prefix}}/lib/glibc-{{version.marketing}}"
160+
- CFLAGS="-O2 $EXTRA_CFLAGS -fPIC"
161+
CPP="gcc -E"
162+
LDFLAGS="$LDFLAGS"
163+
libc_cv_slibdir="$LIBDIR"
164+
libc_cv_rtlddir="$LIBDIR"
165+
libc_cv_complocaledir="$LIBDIR/locale"
166+
libc_cv_static_pie=no
167+
../configure $ARGS
168+
169+
- run: MAKE_JOBS={{ hw.concurrency }}
170+
- run: rm -f libc_nonshared.a libc_pic.a libc_pic.os */stamp.os */stamp.oS
171+
if: <2.19
172+
- make --jobs $MAKE_JOBS CFLAGS-regexp.c=-fno-common CFLAGS-obstack.c=-fno-common
122173
- make install
123174

124175
# Self-relocate generated scripts so the bottle works at any prefix.
125-
- run: |
126-
for s in $SCRIPTS; do
127-
test -f $s || continue
128-
sed -i 's|{{prefix}}|"$(cd "$(dirname "$0")/.." \&\& pwd)"|' $s
129-
done
176+
- run:
177+
- for s in $SCRIPTS; do
178+
- test -f $s || continue
179+
- sed -i 's|{{prefix}}|"$(cd "$(dirname "$0")/.." \&\& pwd)"|' $s
180+
- done
130181
working-directory: ${{prefix}}/bin
131182

132183
# Convenience: arch-agnostic ld.so symlink that points into the
@@ -139,17 +190,14 @@ build:
139190
# downstream `-L $LIBDIR -lc` works after the bottle relocates from
140191
# /opt to ~/.pkgx (or anywhere else). Detect via first-line marker,
141192
# not file(1) — not on the test-sandbox PATH.
142-
- run: |
143-
PREFIX_FINAL=$(echo "{{prefix}}" | sed 's/+brewing$//')
144-
for f in $(find . -maxdepth 2 -type f -name '*.so'); do
145-
if head -c 16 "$f" | grep -q "GNU ld script"; then
146-
sed -i \
147-
-e 's|{{prefix}}/lib/glibc-{{version.marketing}}/||g' \
148-
-e "s|$PREFIX_FINAL/lib/glibc-{{version.marketing}}/||g" \
149-
"$f"
150-
echo "relocated linker script $f"
151-
fi
152-
done
193+
- run:
194+
- PREFIX_FINAL=$(echo "{{prefix}}" | sed 's/+brewing$//')
195+
- for f in $(find . -maxdepth 2 -type f -name '*.so'); do
196+
- if head -c 16 "$f" | grep -q "GNU ld script"; then
197+
- sed -i -e 's|{{prefix}}/lib/glibc-{{version.marketing}}/||g' -e "s|$PREFIX_FINAL/lib/glibc-{{version.marketing}}/||g" "$f"
198+
- echo "relocated linker script $f"
199+
- fi
200+
- done
153201
working-directory: ${{prefix}}/lib
154202

155203
# PT_INTERP is absolute and cannot use $ORIGIN or fall back. Do not
@@ -161,18 +209,18 @@ build:
161209
# Running an ELF through ld.so explicitly ignores the ELF's own
162210
# PT_INTERP, so the inner libexec binaries may keep whatever glibc's
163211
# build installed. The wrapper supplies --library-path explicitly.
164-
- run: |
165-
for dir in bin sbin; do
166-
mkdir -p "{{prefix}}/libexec/glibc-$dir"
167-
for f in "{{prefix}}/$dir"/*; do
168-
[ -f "$f" ] && [ ! -L "$f" ] || continue
169-
patchelf --print-interpreter "$f" >/dev/null 2>&1 || continue
170-
mv "$f" "{{prefix}}/libexec/glibc-$dir"
171-
sed -e "s/@LDSO@/$LDSO/g" -e "s/@DIR@/$dir/g" "$PROP" >$f
172-
chmod 775 $f
173-
echo "wrapped $f"
174-
done
175-
done
212+
- run:
213+
- for dir in bin sbin; do
214+
- mkdir -p "{{prefix}}/libexec/glibc-$dir"
215+
- for f in "{{prefix}}/$dir"/*; do
216+
- '[ -f "$f" ] && [ ! -L "$f" ] || continue'
217+
- test "$(head -c 4 "$f" | od -An -tx1 | tr -d ' \n')" = "7f454c46" || continue
218+
- mv "$f" "{{prefix}}/libexec/glibc-$dir"
219+
- sed -e "s/@LDSO@/$LDSO/g" -e "s/@DIR@/$dir/g" "$PROP" > "$f"
220+
- chmod 755 "$f"
221+
- echo "wrapped $f"
222+
- done
223+
- done
176224
prop: |
177225
#!/bin/sh
178226
@@ -232,7 +280,7 @@ build:
232280
# bin/* work after relocation.
233281
test:
234282
dependencies:
235-
gnu.org/gcc: "*"
283+
gnu.org/gcc: 14
236284
env:
237285
x86-64:
238286
LDSO: ld-linux-x86-64.so.2
@@ -247,8 +295,10 @@ test:
247295
- test -L "{{prefix}}/bin/ld.so" || { echo "missing bin/ld.so symlink"; exit 1; }
248296

249297
# 2) Loader self-test (was SIGSEGV before the fix-patchelf skip).
250-
- echo "--- ld.so --version ---"
251-
- '"$LIBDIR/$LDSO" --version | head -2'
298+
# Older loaders treat bare `--version` as the executable name, so execute
299+
# libc.so.6 through this bottle's loader instead.
300+
- echo "--- ld.so libc.so.6 --version ---"
301+
- '"$LIBDIR/$LDSO" --library-path "$LIBDIR" "$LIBDIR/libc.so.6"'
252302

253303
# 3) Compile test.c dynamically against the bottle's headers /
254304
# libs / loader. -B $LIBDIR picks our Scrt1.o / crti.o / crtn.o
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# rtld-pkgx-alias-routines
2+
ifeq ($(subdir),elf)
3+
sysdep-rtld-routines += xstat fxstat lxstat
4+
endif

0 commit comments

Comments
 (0)