glibc-compat: add static-link mmap shim (32-bit off_t for vendor V2 blobs)#2110
Merged
Merged
Conversation
Vendor glibc binaries from the V2 era (e.g. hi3520dv200's libmpi.so) were built without _FILE_OFFSET_BITS=64 so their mmap() takes a 32-bit off_t. musl's mmap() exports 64-bit off_t — when libmpi dynamic-links against musl on a modern rootfs, the high 32 bits of the offset arg come from uninitialised stack and the kernel sees a garbage pgoff, rejecting with EINVAL. Symptom on hi3520dv200: every HI_MPI_VENC_CreateChn returns 0xa007800c (EN_ERR_VENC_NOMEM) because libmpi can't mmap the model_buf via /dev/venc. Confirmed via LD_PRELOAD trace shim that wraps mmap(): the syscall reaches the kernel with off=0x402b65d8 — a userspace VA (varies between runs with ASLR), clearly stack garbage. Fix: add glibc-compat-static.c with a 32-bit off_t mmap()/mmap64() wrapper that goes straight to SYS_mmap2 bypassing musl's libc wrapper. Same pattern as #2000 (uclibc-compat-static for hi3516cv100). The function must be statically linked into the consumer executable (not in a .so) so the dynamic linker resolves vendor .so imports of mmap to the executable's symbol table BEFORE musl — putting it in a .so would override musl process-wide and break musl's own internal mmap callers (malloc, dlopen, etc.). - glibc-compat/src/glibc-compat-static.c: new file, mmap()/mmap64() wrappers calling SYS_mmap2 with pgoff - glibc-compat/src/Makefile: build both libglibc-compat.so and libglibc-compat-static.a - glibc-compat/glibc-compat.mk: INSTALL_STAGING=YES, install .a to STAGING_DIR so dependent packages can link -lglibc-compat-static - Makefile (BUNDLE_SDK): produce libglibc-compat.so and libglibc-compat-static.a in the published toolchain SDK tarball, mirroring the existing uclibc-compat handling Verified on lab DVR (openipc-hi3520dv200.dlab.torturelabs.com): linking dvr_home with the mmap shim makes HI_MPI_VENC_CreateChn succeed on all 4 channels. Refs: #1992 (toolchain ABI audit), #1993 (cv100 stat shim), #2000 (cv100 static-link split)
8f8363c to
028db19
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Mirror of #2000 but for glibc vendor binaries (V2 SoCs like hi3520dv200).
Vendor glibc binaries from the V2 era (`libmpi.so` etc.) were built without `_FILE_OFFSET_BITS=64` — their `mmap()` import takes a 32-bit `off_t`. musl's `mmap()` exports 64-bit `off_t`. When libmpi dynamic-links against musl, the high 32 bits of the offset come from uninitialised stack; the kernel sees a garbage pgoff and rejects with `EINVAL`.
Symptom on hi3520dv200: every `HI_MPI_VENC_CreateChn` returns `0xa007800c` (`EN_ERR_VENC_NOMEM`) because libmpi can't mmap the model_buf via `/dev/venc`. Confirmed via an `LD_PRELOAD` trace shim that wraps `mmap()`:
```
mmap(fd=28[/dev/venc], off=0x402b65d8, len=229376) = -1 errno=22 EINVAL
mmap err,page addr:-1896943616 u32PagePhy size:114688
VENC: CreateChn(0) 0xa007800c
```
`0x402b65d8` is a userspace VA (lower 12 bits constant `0x5d8`, upper bits vary between runs with ASLR) — pure stack garbage. The vendor's printed "page addr / u32PagePhy size" values are libmpi-internal state, not the real mmap args, so the message is misleading.
Fix
Mirror PR #2000's pattern, scoped to glibc vendor blobs:
The wrapper must be statically linked into the consumer executable. Putting it in a shared library would override musl's mmap process-wide and break musl's own internal callers (malloc, dlopen, …) — that's exactly the bug PR #2000 fixed for uclibc-compat.
Why static linking works
The dynamic linker resolves an undefined import like `mmap` from libmpi.so by walking the global symbol scope: the executable first, then `DT_NEEDED` libraries in order. With `-Wl,--export-dynamic-symbol=mmap` on the executable (or just having the symbol from a static lib that gets pulled in via reference), the executable's `mmap` enters its `.dynsym` and libmpi binds against it instead of musl. musl's own internal mmap calls still bind locally because musl uses internal versions / direct syscalls and isn't subject to symbol interposition for its own callers.
Test plan
Refs: #1992 (toolchain ABI audit), #1993 (cv100 stat shim), #2000 (cv100 static-link split), #2109 (hi3520dv200 opensdk wiring that built on top of glibc-compat).