From 3fee0ae7be5a31676f13257bfce9d27555e2d409 Mon Sep 17 00:00:00 2001 From: Shokunin <30949000+tetrisgm@users.noreply.github.com> Date: Tue, 13 Oct 2026 00:02:09 -0700 Subject: [PATCH] Linux tcc: build without the legacy bounds-checking runtime (glibc 2.34+) tcc 0.9.27's lib/bcheck.c uses __malloc_hook, removed in glibc 2.34, so the pinned build failed on Ubuntu 24.04 (lib/bcheck.c:738). Shards never use -b; the build now passes BCHECK_O= unconditionally, keeping every other libtcc1.a object. The bundle smoke also clears LIBRARY_PATH, CC and GCC_EXEC_PREFIX and checks shards import no bounds-checking symbols. Verified: linux_tcc_bundle_smoke_test passes on Ubuntu 24.04 x86_64 (glibc 2.39, gcc + libc6-dev installed, so host headers exist but are not used) and on Steam Runtime sniper (glibc 2.31). Co-Authored-By: Claude Opus 5.5 --- lib/recomp-net | 2 +- runtime/tests/test_linux_tcc_bundle_smoke.py | 8 ++++++-- tools/release_stage.py | 9 +++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/recomp-net b/lib/recomp-net index e5305930..b1eab87b 160000 --- a/lib/recomp-net +++ b/lib/recomp-net @@ -1 +1 @@ -Subproject commit e53059306824edf4f0aec4aae5ae65151b18535f +Subproject commit b1eab87bf3c011da8c22890601c0e659f1f89fbb diff --git a/runtime/tests/test_linux_tcc_bundle_smoke.py b/runtime/tests/test_linux_tcc_bundle_smoke.py index 0bdf883e..2daca2a8 100644 --- a/runtime/tests/test_linux_tcc_bundle_smoke.py +++ b/runtime/tests/test_linux_tcc_bundle_smoke.py @@ -134,8 +134,8 @@ def main(): out = os.path.join(work, 'shard_f%d.so' % flavor) env_keep = dict(os.environ) os.environ['PATH'] = '/nonexistent' # no host compiler can help - os.environ.pop('CPATH', None) - os.environ.pop('C_INCLUDE_PATH', None) + for v in ('CPATH', 'C_INCLUDE_PATH', 'LIBRARY_PATH', 'CC', 'GCC_EXEC_PREFIX'): + os.environ.pop(v, None) try: ok = co._compile_dll_tcc(c_path, out, [inc], flavor, tcc) finally: @@ -153,6 +153,10 @@ def main(): if not hasattr(lib, 'func_80114000'): print('FAIL flavor %d: func_80114000 not exported' % flavor) fails += 1 + nm = os.popen('nm -D --undefined-only %s' % out).read() + if 'bound' in nm or '__bound' in nm: + print('FAIL flavor %d: the shard references bounds-checking symbols' % flavor) + fails += 1 print('ok flavor %d: shard built by the bundled tcc + musl and loaded (abi 0x%X)' % (flavor, abi)) return 1 if fails else 0 diff --git a/tools/release_stage.py b/tools/release_stage.py index 7df86199..00bd0c6c 100644 --- a/tools/release_stage.py +++ b/tools/release_stage.py @@ -706,8 +706,13 @@ def stage_linux_tcc(toolchain, dl_cache, pins, log=print): cc = os.environ.get('CC', 'cc') _run_build(['./configure', '--prefix=' + inst, '--cc=' + cc, '--extra-cflags=-O2'], tcc_src, 'tcc configure') - _run_build(['make', '-j%d' % (os.cpu_count() or 2)], tcc_src, 'tcc build') - _run_build(['make', 'install'], tcc_src, 'tcc install') + # BCHECK_O= : leave out lib/bcheck.o, tcc's legacy bounds-checking runtime + # (-b). Shards never use it, and it does not build against current glibc + # (it uses __malloc_hook, removed in glibc 2.34: Ubuntu 24.04 fails at + # lib/bcheck.c:738). libtcc1.a keeps every other object. Unconditional, + # so every build host produces the same bundle. + _run_build(['make', '-j%d' % (os.cpu_count() or 2), 'BCHECK_O='], tcc_src, 'tcc build') + _run_build(['make', 'install', 'BCHECK_O='], tcc_src, 'tcc install') musl = get_pinned_archive(pins['musl_url'], pins['musl_sha256'], os.path.join(dl_cache, _url_basename(pins['musl_url'])),