[Bug]: Non-deterministic .gnu.hash generation when building from Windows symlinked directory in WSL
- Dominant language
- No language data
- Stars
- 2.3k
- Forks
- 310
- PR merge metrics
- No merged PRs in 30d
Description
### Description
Non-deterministic .gnu.hash generation when building native libraries from symlinked directory
Environment:
- NDK: r29 (29.0.14206865)
- Platform: Linux (WSL2) - 6.6.87.2-microsoft-standard-WSL2
- Gradle: 8.13
- AGP: (check build.gradle.kts for com.android.application version)
- CMake: (using SDK default)
Issue:
Native library builds produce non-deterministic output when the project is located in a symlinked directory. Specifically, the .gnu.hash section differs between builds despite identical source code and build configuration.
Runtime Impact:
The non-deterministic builds from the symlinked directory also crash at runtime, while the deterministic non-symlink builds work correctly. The crash occurs during library loading with SIGSEGV (signal 11) in the Android dynamic linker:
#00 pc 00000000000624c8 /apex/com.android.runtime/bin/linker64 (soinfo_do_lookup_impl+228)
#01 pc 0000000000061a5c /apex/com.android.runtime/bin/linker64 (plain_relocate_impl+328)
#02 pc 000000000005ffdc /apex/com.android.runtime/bin/linker64 (soinfo::relocate+608)
The crash happens during symbol resolution when the dynamic linker tries to relocate symbols in libdelaycam_tflite.so. This suggests the corrupted .gnu.hash table is causing the linker to fail during runtime symbol lookup, not just a build reproducibility issue.
Setup:
- Symlink: ~/d/delaycam → /mnt/d/python/delaycam
- Control directory (no symlink): ~/delaycam-test (copy of same code)
Steps to Reproduce:
1. Build native library from symlinked directory (~/d/delaycam)
2. Note APK/library checksum
3. Clean and rebuild from same directory
4. Compare checksums
Expected Behavior:
Identical source code + identical build config = identical binary output (deterministic builds)
Actual Behavior:
- Non-symlink builds: Deterministic (same checksum every time)
- Symlink builds: Non-deterministic (different checksum each build)
Evidence (NDK r29 builds):
Working (non-symlink):
- Build 1: e987d815ebe3b75d8f5601c0a9e33326
- Build 2: e987d815ebe3b75d8f5601c0a9e33326 ✓ Identical
Symlinked:
- Build 1: 1ca199410fa990e9513343d5f249f65d
- Build 2: 49034b0ac716b72e56ae0999333d9a99 ✗ Different
Technical Details:
Analysis of differing bytes shows:
- 12,312 bytes differ between symlink builds (out of 9.3MB)
- 8,188 bytes in .gnu.hash section (hash table for dynamic linker)
- 4,099 bytes in .dynstr (dynamic string table)
- Build ID differs (expected, computed from binary)
- Code sections (.text, .rodata, .data) are identical (same size, same content)
The .gnu.hash section contains completely different random-looking data between builds, suggesting non-deterministic hash function or iteration over unordered data structure during linking.
Tried to attach, wouldn't let me, can provide on request: three libdelaycam_tflite.so files (28MB total):
- working-libdelaycam_tflite.so - deterministic non-symlink build
- symlinked1-libdelaycam_tflite.so - first symlink build
- symlinked2-libdelaycam_tflite.so - second symlink build (differs from first)
### Upstream bug
_No response_
### Commit to cherry-pick
_No response_
### I am using a supported NDK
- [x] I have checked and the NDK I'm using is currently supported
### Affected versions
r29, r28
### Host OS
Linux
### Host OS version
Ubuntu 24.04.2 LTS (WSL2) - Kernel 6.6.87.2-microsoft-standard-WSL2
### Affected ABIs
arm64-v8a
Contributor guide
Research direction
The report names build.gradle.kts, the symlinked ~/d/delaycam directory, the ~/delaycam-test control copy, and the affected .so files. First reproduce clean rebuilds in both locations and compare checksums plus the reported .gnu.hash and .dynstr sections. Done means identifying the r28/r29 source of the nondeterminism and linker crash, with a reproducible verification.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cmake, linux
- Domain
- build-system, operating-systems
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100