Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/sample-application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@ jobs:
./scripts/set-dsn-aos.mjs
./scripts/build-android.sh -PreactNativeArchitectures=x86

- name: Check 16 KB native library alignment
# Only Sentry-owned libraries are checked: third-party/React Native
# libraries are aligned by their own build (RN ships arm64 at 16 KB but
# x86 at 4 KB, and CI builds x86), so a whole-APK check is not
# meaningful here. Guards against regressing #6394.
run: ./scripts/check-android-16kb-alignment.sh ${{ env.REACT_NATIVE_SAMPLE_PATH }}/app.apk 'libsentry'

- name: Archive Android App
if: ${{ matrix.rn-architecture == 'new' && matrix.build-type == 'production' }}
run: |
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
> make sure you follow our [migration guide](https://docs.sentry.io/platforms/react-native/migration/) first.
<!-- prettier-ignore-end -->
## Unreleased

### Fixes

- Force 16 KB ELF alignment for `libsentry-tm-perf-logger.so` so it does not break 16 KB page size compatibility on Android 15+ ([#6396](https://github.com/getsentry/sentry-react-native/pull/6396))

## 8.17.0

### Features
Expand Down
16 changes: 16 additions & 0 deletions packages/core/android/src/main/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,22 @@ target_link_libraries(
ReactAndroid::reactnative
)

# Force 16 KB ELF LOAD-segment alignment. The NDK linker only defaults to a
# 16 KB `max-page-size` from r28 onwards; RN 0.86 / Expo SDK 57 still build
# with NDK 27, whose default is 4 KB. Every other `.so` bundled by RN/AGP is
# already 16 KB aligned, so without this flag `libsentry-tm-perf-logger.so`
# is the lone misaligned library and trips Android 15+'s 16 KB page-size
# compatibility check (and Google Play's 16 KB requirement) for the whole
# app โ€” even for hosts that never opt in to `enableTurboModuleTracking`,
# since the library is packaged whenever the New Architecture is enabled.
# On NDK r28+ this option is a redundant no-op.
# https://github.com/getsentry/sentry-react-native/issues/6394
target_link_options(
sentry-tm-perf-logger
PRIVATE
"-Wl,-z,max-page-size=16384"
)

# Note: we deliberately do NOT pass `-Wl,--strip-all` (or similar) here.
# Android Gradle Plugin's `StripDebugSymbolsTask` already strips the .so for
# the packaged APK while preserving the unstripped artefact under
Expand Down
105 changes: 105 additions & 0 deletions scripts/check-android-16kb-alignment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#!/bin/bash

# Verifies native libraries (`.so`) bundled inside an Android APK/AAB have
# their ELF LOAD segments aligned to at least 16 KB (`p_align >= 0x4000`).
#
# Android 15+ devices with a 16 KB page size (and Google Play's 16 KB
# requirement) reject apps that ship a `.so` aligned to only 4 KB. Libraries
# built from source with NDK r27 and earlier default to 4 KB, so this check
# guards against a regression like https://github.com/getsentry/sentry-react-native/issues/6394
# where `libsentry-tm-perf-logger.so` shipped misaligned.
#
# By default every `.so` is checked. Pass a name filter (a regex matched
# against each library's path) to restrict the check to the libraries this
# repo actually controls โ€” third-party/React Native libraries are aligned by
# their own build (RN ships arm64 at 16 KB but x86 at 4 KB, so a whole-APK
# check is not meaningful on the x86 builds CI produces).
#
# Usage: scripts/check-android-16kb-alignment.sh <path-to-apk-or-aab> [name-filter-regex]
# e.g. scripts/check-android-16kb-alignment.sh app.apk 'libsentry'
#
# `readelf` is resolved from (in order): $READELF, `llvm-readelf`, `readelf`.

set -euo pipefail

REQUIRED_ALIGN=16384 # 16 KB, expressed in bytes

apk="${1:-}"
name_filter="${2:-}"
if [[ -z "$apk" || ! -f "$apk" ]]; then
echo "usage: $0 <path-to-apk-or-aab> [name-filter-regex]" >&2
exit 2
fi

readelf_bin="${READELF:-}"
if [[ -z "$readelf_bin" ]]; then
if command -v llvm-readelf >/dev/null 2>&1; then
readelf_bin="llvm-readelf"
elif command -v readelf >/dev/null 2>&1; then
readelf_bin="readelf"
else
echo "error: neither 'llvm-readelf' nor 'readelf' found on PATH (set \$READELF to override)" >&2
exit 2
fi
fi

workdir="$(mktemp -d)"
trap 'rm -rf "$workdir"' EXIT

# Extract only the native libraries. APK and AAB both store them under a
# top-level `lib/` (APK) or `base/lib/` (AAB) directory.
unzip -qq -o "$apk" 'lib/*' 'base/lib/*' -d "$workdir" 2>/dev/null || true

libs=()
while IFS= read -r lib; do
if [[ -n "$name_filter" && ! "$lib" =~ $name_filter ]]; then
continue
fi
libs+=("$lib")
done < <(find "$workdir" -type f -name '*.so' | sort)
if [[ ${#libs[@]} -eq 0 ]]; then
if [[ -n "$name_filter" ]]; then
echo "error: no .so libraries matching /$name_filter/ found inside $apk" >&2
else
echo "error: no .so libraries found inside $apk" >&2
fi
exit 2
fi

misaligned=()
for lib in "${libs[@]}"; do
rel="${lib#"$workdir"/}"
# Smallest LOAD-segment alignment in this library, in bytes. `readelf`
# prints the align column as a hex literal (e.g. `0x4000`); bash arithmetic
# parses the `0x` prefix directly, so we avoid gawk-only `strtonum`.
min_align=0
while IFS= read -r align_hex; do
[[ -z "$align_hex" ]] && continue
align=$((align_hex))
if [[ "$min_align" -eq 0 || "$align" -lt "$min_align" ]]; then
min_align="$align"
fi
done < <("$readelf_bin" -lW "$lib" | awk '$1 == "LOAD" { print $NF }')

if [[ "$min_align" -eq 0 ]]; then
echo "warn: $rel โ€” no LOAD segments found, skipping" >&2
continue
fi

if [[ "$min_align" -lt "$REQUIRED_ALIGN" ]]; then
misaligned+=("$rel (align=$min_align)")
printf 'FAIL: %-48s align=%d (need >= %d)\n' "$rel" "$min_align" "$REQUIRED_ALIGN"
else
printf 'OK: %-48s align=%d\n' "$rel" "$min_align"
fi
done

echo
if [[ ${#misaligned[@]} -gt 0 ]]; then
echo "โœ– ${#misaligned[@]} library/libraries are not 16 KB aligned:" >&2
for m in "${misaligned[@]}"; do echo " - $m" >&2; done
echo " Pass -Wl,-z,max-page-size=16384 when linking, or build with NDK r28+." >&2
exit 1
fi

echo "โœ” all ${#libs[@]} libraries are >= 16 KB aligned"
Loading