Skip to content

i686-linux bootstrap fails on filesystems with 64-bit inodes #253274

@trofi

Description

@trofi

Describe the bug

xgcc build fails for me due to patchelf using stat with 32-bit glibc API.

My guess is that patchelf from bootstrapTools was built without -D_FILE_OFFSET_BITS=64 and now fails on modern filesystems.

Steps To Reproduce

  1. Have /nix/store on btrfs.
  2. Get to the point when new inodes are 64-bit.
  3. Try to build gcc:
$ nix build --no-link nixpkgs#pkgsi686Linux.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.cc.cc
$ nix build --no-link nixpkgs#pkgsi686Linux.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.cc.cc --rebuild
error: builder for '/nix/store/vcbclad7nm49d213vxg0j5jzfr2ad6d2-xgcc-12.3.0.drv' failed with exit code 1;
       last 10 log lines:
       > Moving /nix/store/krwb5yd6gs45ws6h4n89byrmlrfb72an-xgcc-12.3.0/lib/libssp_nonshared.la to /nix/store/m9kfsb7ygp4f2ip0cdj0g1kbcgpi10r3-xgcc-12.3.0-lib/lib/libssp_nonshared.la
       > Moving /nix/store/krwb5yd6gs45ws6h4n89byrmlrfb72an-xgcc-12.3.0/lib/libstdc++.la to /nix/store/m9kfsb7ygp4f2ip0cdj0g1kbcgpi10r3-xgcc-12.3.0-lib/lib/libstdc++.la
       > Moving /nix/store/krwb5yd6gs45ws6h4n89byrmlrfb72an-xgcc-12.3.0/lib/libstdc++fs.la to /nix/store/m9kfsb7ygp4f2ip0cdj0g1kbcgpi10r3-xgcc-12.3.0-lib/lib/libstdc++fs.la
       > Moving /nix/store/krwb5yd6gs45ws6h4n89byrmlrfb72an-xgcc-12.3.0/lib/libsupc++.la to /nix/store/m9kfsb7ygp4f2ip0cdj0g1kbcgpi10r3-xgcc-12.3.0-lib/lib/libsupc++.la
       > Moving /nix/store/krwb5yd6gs45ws6h4n89byrmlrfb72an-xgcc-12.3.0/lib/libubsan.la to /nix/store/m9kfsb7ygp4f2ip0cdj0g1kbcgpi10r3-xgcc-12.3.0-lib/lib/libubsan.la
       > Moving /nix/store/krwb5yd6gs45ws6h4n89byrmlrfb72an-xgcc-12.3.0/share/gcc-12.3.0/python to /nix/store/m9kfsb7ygp4f2ip0cdj0g1kbcgpi10r3-xgcc-12.3.0-lib/share/gcc-12.3.0/python
       > Removing empty /nix/store/krwb5yd6gs45ws6h4n89byrmlrfb72an-xgcc-12.3.0/share/gcc-12.3.0/ and (possibly) its parents
       > /nix/store/66jp1ap3iffxny1pqih0rqqw4ha62cmd-bootstrap-stage-xgcc-stdenv-linux/setup: line 164: type: install_name_tool: not found
       > preFixupLibGccPhase
       > stat: Value too large for defined data type
       For full logs, run 'nix log /nix/store/vcbclad7nm49d213vxg0j5jzfr2ad6d2-xgcc-12.3.0.drv'.

Expected behavior

gcc build build.

Additional context

The problem is in outdated patchelf binary in the bootstrapTools:

$ nix develop --impure --expr 'with import ./. {}; pkgsi686Linux.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.__bootPackages.stdenv.cc.cc.overrideAttrs (oa: { preFixupLibGccPhase = "set -x\n" + oa.preFixupLibGccPhase; })'
$$ genericBuild
...
++ patchelf --set-rpath '' /home/slyfox/dev/git/nixpkgs/outputs/libgcc/lib/libgcc_s.so.1
stat: Value too large for defined data type

Re-entering nix develop again and running manually:

$ patchelf --set-rpath '' $libgcc/lib/libgcc_s.so.1
stat: Value too large for defined data type
$ which patchelf
/nix/store/i9v173g8a5wwi8i8fd2wmdyr8ix6mla1-bootstrap-tools/bin/patchelf

It still uses 32-bit stat:

$ nm -DC /nix/store/i9v173g8a5wwi8i8fd2wmdyr8ix6mla1-bootstrap-tools/bin/patchelf |& fgrep stat
         U __xstat@GLIBC_2.0

If we compare against nowaday's patchelf:

$ nm -DC $(nix-build --no-link '<nixpkgs>' -A patchelf --argstr system i686-linux )/bin/patchelf |& fgrep stat
         U stat64@GLIBC_2.33
         U std::basic_ios<char, std::char_traits<char> >::clear(std::_Ios_Iostate)@GLIBCXX_3.4

What is 64-bit about my file?

$ stat /nix/store/i9v173g8a5wwi8i8fd2wmdyr8ix6mla1-bootstrap-tools/bin/patchelf
  File: /nix/store/i9v173g8a5wwi8i8fd2wmdyr8ix6mla1-bootstrap-tools/bin/patchelf
  Size: 152960          Blocks: 304        IO Block: 4096   regular file
Device: 1dh/29d Inode: 3904117450  Links: 2
Access: (0555/-r-xr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-08-21 23:52:46.000000000 +0100
Modify: 1970-01-01 01:00:01.000000000 +0100
Change: 2023-08-21 23:52:46.863509707 +0100
 Birth: -

It's the inode number: 3904117450.

$ man 2 stat
...
       EOVERFLOW
              pathname  or fd refers to a file whose size, inode number, or number of blocks cannot be represented in, respectively, the types off_t, ino_t, or blkcnt_t.  This error can occur when, for exam‐
              ple, an application compiled on a 32-bit platform without -D_FILE_OFFSET_BITS=64 calls stat() on a file whose size exceeds (1<<31)-1 bytes.

My guess is that patchelf from bootstrapTools was built without -D_FILE_OFFSET_BITS=64 and now fails on modern filesystems.

If we run up to date binary it works fine:

$ nix build -f. patchelf --argstr system i686-linux
$ realpath ./result/bin/patchelf
/nix/store/b4ashsdd8c5snl608hfmabp9pxn4hll7-patchelf-0.15.0/bin/patchelf

$ /nix/store/b4ashsdd8c5snl608hfmabp9pxn4hll7-patchelf-0.15.0/bin/patchelf --set-rpath '' $libgcc/lib/libgcc_s.so.1
<ok>

Metadata

[user@system:~]$ nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 6.4.11, NixOS, 23.11 (Tapir), 23.11.20230901.9d33ec8`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.17.0`
 - channels(root): `""`
 - channels(slyfox): `""`
 - nixpkgs: `/run/current-system/sw/share/nixos-flakes/inputs/nixpkgs`
output here

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions