Align native .so LOAD segments to 16 KB (blocks any targetSdk 35+ upload)#9
Open
xroche wants to merge 3 commits into
Open
Align native .so LOAD segments to 16 KB (blocks any targetSdk 35+ upload)#9xroche wants to merge 3 commits into
xroche wants to merge 3 commits into
Conversation
Play checks two things and we only satisfied one. ZIP-entry alignment already passed (zipalign -P 16, extractNativeLibs=false), which is what our notes recorded. ELF LOAD alignment did not: every shipped .so linked at 4 KB, so an upload at targetSdk 35 would be rejected. lld shifts vaddr rather than file offsets, so the .so bytes and the release APK size are identical either way. NDK r28 makes 16 KB the default, but it is not needed here and can stay a separate bump. The CI guard is there because this regresses silently: nothing in a normal build reports segment alignment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com>
Review found the guard could pass on a subset. find runs inside a process substitution, where set -e cannot see its exit status and pipefail does not reach, so a truncated walk checked whatever it got and still printed the success banner. The old empty-list test only ever proved that at least one .so turned up. Comparing the walk against the archive's own listing asserts completeness instead, and catches unzip under-extracting for free. Confirmed against a find stub that emits one path and exits 1: the previous guard reported "16 KB aligned: 1 .so" and exited 0, this one exits 1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com>
Review follow-ups, none of them blocking. The zero-.so APK, which is the likelier regression here, died in the extraction step with unzip's own "filename not matched" and rc 11 before any of our checks ran; it now says what actually happened, and a genuinely unreadable archive is reported separately rather than sharing that message. find grows -type f so a directory named foo.so cannot reach readelf. That also removes one of the two ways a count could agree over different sets, the other needing a duplicate entry name that no Android build tool emits. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Xavier Roche <roche@httrack.com>
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.
Every
.sowe ship links its LOAD segments at 4 KB, which Play rejects at targetSdk 35+. Play checks ZIP-entry alignment and ELF segment alignment separately, and the first already passed, so the problem was invisible to the checks we had.The fix is one linker flag on the current NDK r26d. The release APK comes out the same size either way, because lld shifts vaddr rather than file offsets. The
.soare not byte-identical, sincep_align, the RW segmentp_vaddrand the relocations tracking it all move, but nothing is padded or reordered. NDK r28 only makes 16 KB the default, so that bump stays separate.The CI guard matters as much as the flag, since alignment regresses with no build error. It fails on a 4 KB build and passes on a 16 KB one, and it compares its walk against the archive listing so a partial enumeration cannot pass on a subset.
Known gaps, deliberately out of scope: the guard asserts ELF
p_alignonly, while Play also wants ZIP-entry alignment and RELRO. ZIP alignment currently passes on AGP 8.6 defaults rather than on anything we set, so an AGP downgrade or a hand-set packaging option would produce an APK that Play rejects and this guard passes green. Nothing builds or checks an AAB either, and that is the artifact Play actually takes. None of it bites while targetSdk is 25, but all of it wants a tracker note before we upload.