Skip to content

fix: remove redundant -Wl,-z,relro,-z,now to fix UnsatisfiedLinkError on 16k-page-size builds#563

Merged
wysaid merged 3 commits intomasterfrom
fix/relro-oom-16k-page-size
Feb 21, 2026
Merged

fix: remove redundant -Wl,-z,relro,-z,now to fix UnsatisfiedLinkError on 16k-page-size builds#563
wysaid merged 3 commits intomasterfrom
fix/relro-oom-16k-page-size

Conversation

@wysaid
Copy link
Copy Markdown
Owner

@wysaid wysaid commented Feb 21, 2026

Problem

Fixes #562 — crash on Samsung S21 Plus (Android 14) with 3.1.1-16k-min:

Fatal Exception: java.lang.UnsatisfiedLinkError
dlopen failed: can't enable GNU RELRO protection for libCGEExt.so: Out of memory

Root Cause

target_link_options(CGE PUBLIC ... -Wl,-z,relro,-z,now) propagated these flags to CGEExt via CMake's PUBLIC interface linkage. With 16KB page alignment enabled, the linker pads PT_GNU_RELRO to 16KB boundaries, making MemSiz (~10KB) far larger than the actual RW LOAD segment (~1.5KB). The Android dynamic linker then calls mprotect() over a larger-than-mapped region, which fails with ENOMEM on memory-pressured devices.

Android API 23+ already enforces full RELRO by default — these flags are redundant and harmful here.

Verified with readelf (arm64 libCGEExt.so)

Bug version (3.1.1-16k-min, with relro flags) Fixed version
RW LOAD MemSiz 0x0610 = 1,552 bytes 0x0628 = 1,576 bytes
PT_GNU_RELRO MemSiz 0x28b0 = 10,416 bytes → padded to 16KB at runtime 0x3f50 = 16,208 bytes ≈ 16KB ✓

In the bug version the RELRO MemSiz (10,416) far exceeds FileSiz (1,552), causing the out-of-bounds mprotect() failure.

Changes

library/src/main/jni/CMakeLists.txt

  • Remove -Wl,-z,relro,-z,now from target_link_options
  • Change scope from PUBLIC to PRIVATE for -fPIE -fPIC -pie (no-ops for shared libraries, no need to propagate)
  • Retain PUBLIC scope for -Wl,-z,max-page-size=16384 so CGEExt inherits the 16KB alignment flag automatically via CMake interface propagation

cgeDemo/build.gradle

  • Add disableVideoModule() helper function
  • Make the testDemoWithGradleLibs dependency dynamic: automatically selects the correct AAR variant suffix (-16k, -min, -16k-min) based on local.properties flags, instead of hardcoding 3.1.1

How to Verify

Build the demo with testDemoWithGradleLibs=true, enable16kPageSizes=true, disableVideoModule=true — the dependency will resolve to org.wysaid:gpuimage-plus:3.1.1-16k-min (the crashing version) for regression testing. The fixed libCGEExt.so can be verified statically:

llvm-readelf -l libCGEExt.so | grep -E 'LOAD|GNU_RELRO'
# MemSiz of GNU_RELRO should be >= MemSiz of RW LOAD segment

Summary by CodeRabbit

  • Bug Fixes

    • Fixed a crash on devices using 16KB page sizes (UnsatisfiedLinkError), improving stability on affected Android devices.
  • Chores

    • Bumped app version to 3.1.2.
    • Stronger non-Debug optimizations for improved production performance.
    • Simplified native linking for more robust binaries.
  • Documentation

    • Added changelog entry describing the fix and rationale.

…ge-size builds

Fixes #562 — crash on Samsung S21 Plus (Android 14) with 3.1.1-16k-min:
  dlopen failed: can't enable GNU RELRO protection for libCGEExt.so: Out of memory

Root cause:
  target_link_options(CGE PUBLIC ... -Wl,-z,relro,-z,now) propagated these
  flags to CGEExt via PUBLIC linkage. With 16KB page alignment enabled, the
  linker pads PT_GNU_RELRO to 16KB boundaries, making MemSiz (~10KB) far
  exceed the actual RW LOAD segment size (~1.5KB). The Android dynamic linker
  then calls mprotect() over a region larger than what was mapped, which fails
  with ENOMEM on devices under memory pressure.

  Android (API 23+) enforces full RELRO by default; these flags are redundant.

Changes:
  - CMakeLists.txt: remove -Wl,-z,relro,-z,now; change scope to PRIVATE so
    the remaining -fPIE -fPIC -pie flags do not propagate unnecessarily.
    The -Wl,-z,max-page-size=16384 block retains PUBLIC scope so CGEExt
    inherits 16KB alignment automatically via CMake interface propagation.
  - cgeDemo/build.gradle: add disableVideoModule() helper and make the
    testDemoWithGradleLibs dependency string dynamic (supports all four
    AAR variants: default, -16k, -min, -16k-min)."
Copilot AI review requested due to automatic review settings February 21, 2026 15:29
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 21, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

Updates Gradle to select a dynamic gpuimage-plus variant via new helper flags and bumps the version to 3.1.2; modifies CMake to enable -O3 for non-Debug builds and removes explicit GNU RELRO linker flags; adds a CHANGE.md entry describing the RELRO fix.

Changes

Cohort / File(s) Summary
Demo & top-level Gradle
cgeDemo/build.gradle, build.gradle
Adds disableVideoModule() helper and switches the demo dependency from a static org.wysaid:gpuimage-plus:3.1.1 to a dynamic org.wysaid:gpuimage-plus:${baseVersion}${variant} built from rootProject.ext.android.versionName with optional -16k and -min suffixes. Uses the external dependency only when testDemoWithGradleLibs() is true. Also updates ext.android.versionName from 3.1.1 to 3.1.2.
CMake / native build
library/src/main/jni/CMakeLists.txt
Adds target_compile_options(CGE PRIVATE $<$<NOT:$<CONFIG:Debug>>:-O3>) to enable -O3 for non-Debug builds. Removes previously declared public linker options that included -Wl,-z,relro,-z,now and simplifies linkage while retaining GLESv2, EGL, jnigraphics, log, and android. Inline comments explain rationale and RELRO omission.
Changelog
CHANGE.md
Adds Version 3.1.2 entry describing removal of redundant GNU RELRO linker flags to fix UnsatisfiedLinkError on 16KB-page-size builds (references issue #562).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through Gradle, flags in tow,
I nudged the version so the builds can flow,
I told the linker to lighten its load,
Gave the compiler speed on the non-Debug road,
A crunchy carrot cheer for safer code! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary fix: removing redundant RELRO linker flags to resolve UnsatisfiedLinkError on 16k-page-size builds.
Linked Issues check ✅ Passed The PR fully addresses issue #562 by removing the problematic -Wl,-z,relro,-z,now flags that caused dlopen failures, adding dynamic AAR variant selection for regression testing, and maintaining 16KB page alignment.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the RELRO-related UnsatisfiedLinkError and enabling regression testing; no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/relro-oom-16k-page-size

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes problematic RELRO linker flags from the native build to prevent UnsatisfiedLinkError crashes on 16KB-page-size builds, and improves the demo app’s ability to test published AAR variants by selecting the correct artifact suffix based on local.properties flags.

Changes:

  • Remove -Wl,-z,relro,-z,now from CGE link options (and avoid propagating unrelated link flags to dependents).
  • Keep 16KB page-size linker flags propagated so CGEExt inherits alignment settings when enabled.
  • Update cgeDemo to dynamically pick the correct org.wysaid:gpuimage-plus AAR variant suffix (-16k, -min, -16k-min) during integration testing.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
library/src/main/jni/CMakeLists.txt Adjusts native linker options to avoid RELRO-related runtime load failures on 16KB page-size builds while preserving 16KB alignment propagation.
cgeDemo/build.gradle Adds a helper flag reader and makes the demo’s Maven dependency variant selection match local.properties build flags.

target_compile_options(CGE PRIVATE $<$<NOT:$<CONFIG:Debug>>:-O3>)

target_link_options(CGE PUBLIC -fPIE -fPIC -pie -Wl,-z,relro,-z,now)
# Note: -Wl,-z,relro,-z,now is intentionally omitted here, fixing issue: <https://github.com/wysaid/android-gpuimage-plus/issues/562>
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment uses a full-width Chinese comma (",") in an otherwise English sentence, which can be hard to search for and looks like a typo. Consider replacing it with a normal comma and tightening the wording (e.g., "...omitted here, fixing issue #562: ...").

Suggested change
# Note: -Wl,-z,relro,-z,now is intentionally omitted here fixing issue: <https://github.com/wysaid/android-gpuimage-plus/issues/562>
# Note: -Wl,-z,relro,-z,now is intentionally omitted here, fixing issue #562: <https://github.com/wysaid/android-gpuimage-plus/issues/562>

Copilot uses AI. Check for mistakes.

target_link_options(CGE PUBLIC -fPIE -fPIC -pie -Wl,-z,relro,-z,now)
# Note: -Wl,-z,relro,-z,now is intentionally omitted here, fixing issue: <https://github.com/wysaid/android-gpuimage-plus/issues/562>
target_link_options(CGE PRIVATE -fPIE -fPIC -pie)
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-pie is a linker flag for building position-independent executables; applying it via target_link_options on a library target is unusual and can cause toolchain-specific warnings or errors (especially when the target is SHARED). Consider removing -pie here and, if you still need PIC, prefer POSITION_INDEPENDENT_CODE or target_compile_options(... -fPIC) instead of passing compile flags as link options.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
library/src/main/jni/CMakeLists.txt (2)

83-85: Remove the redundant Chinese comment now that an English equivalent is added.

Lines 83 and 84 say the same thing in two languages. The pre-existing Chinese comment can be dropped.

♻️ Proposed cleanup
-# 非 Debug 模式下添加 -O3
 # Add -O3 in non-Debug mode
 target_compile_options(CGE PRIVATE $<$<NOT:$<CONFIG:Debug>>:-O3>)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@library/src/main/jni/CMakeLists.txt` around lines 83 - 85, Remove the
redundant Chinese comment above the target_compile_options line: delete the
comment "# 非 Debug 模式下添加 -O3" and keep the English comment "# Add -O3 in
non-Debug mode" that precedes the target_compile_options(CGE PRIVATE
$<$<NOT:$<CONFIG:Debug>>:-O3>) statement so only the English comment remains.

88-88: -pie, -fPIE, and -fPIC are inappropriate/redundant link options for a SHARED library.

  • -pie is an executable-only linker flag; lld silently ignores it on shared objects but it is semantically incorrect.
  • -fPIC is a compile-time code-generation flag and is a no-op when forwarded to the linker.
  • -fPIE at link time targets PIE executables, not shared libraries.
  • CMake automatically adds -fPIC to SHARED targets; all three flags are effectively dead weight.

Since the scope is already being narrowed to PRIVATE in this PR, this is a good opportunity to remove all three:

♻️ Proposed cleanup
-# Note: -Wl,-z,relro,-z,now is intentionally omitted here, fixing issue: <https://github.com/wysaid/android-gpuimage-plus/issues/562>
-target_link_options(CGE PRIVATE -fPIE -fPIC -pie)
+# Note: -Wl,-z,relro,-z,now is intentionally omitted here, fixing issue: <https://github.com/wysaid/android-gpuimage-plus/issues/562>
+# Android API 23+ enforces full RELRO by default; no explicit linker hardening flags are needed.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@library/src/main/jni/CMakeLists.txt` at line 88, The target_link_options
invocation for target CGE is adding inappropriate/redundant flags (-pie, -fPIE,
-fPIC) for a SHARED library; remove the entire call to target_link_options(CGE
PRIVATE -fPIE -fPIC -pie) so the linker isn’t passed executable-only or
compile-time flags and let CMake manage -fPIC for the SHARED target, or if you
intended a specific link option keep only valid linker flags and apply them to
target_link_options(CGE ...) appropriately.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@library/src/main/jni/CMakeLists.txt`:
- Line 87: The comment line containing "# Note: -Wl,-z,relro,-z,now is
intentionally omitted here, fixing issue:
<https://github.com/wysaid/android-gpuimage-plus/issues/562>" uses a full-width
Chinese comma (U+FF0C); edit that comment (the CMakeLists.txt comment starting
with "# Note: -Wl,-z,relro,-z,now is intentionally omitted here") and replace
the full-width comma with an ASCII comma (U+002C), and scan nearby comment text
for any other full-width punctuation to normalize to ASCII.

---

Nitpick comments:
In `@library/src/main/jni/CMakeLists.txt`:
- Around line 83-85: Remove the redundant Chinese comment above the
target_compile_options line: delete the comment "# 非 Debug 模式下添加 -O3" and keep
the English comment "# Add -O3 in non-Debug mode" that precedes the
target_compile_options(CGE PRIVATE $<$<NOT:$<CONFIG:Debug>>:-O3>) statement so
only the English comment remains.
- Line 88: The target_link_options invocation for target CGE is adding
inappropriate/redundant flags (-pie, -fPIE, -fPIC) for a SHARED library; remove
the entire call to target_link_options(CGE PRIVATE -fPIE -fPIC -pie) so the
linker isn’t passed executable-only or compile-time flags and let CMake manage
-fPIC for the SHARED target, or if you intended a specific link option keep only
valid linker flags and apply them to target_link_options(CGE ...) appropriately.

- Remove redundant Chinese comment '# 非 Debug 模式下添加 -O3' (keep English only)
- Fix full-width comma (U+FF0C) to ASCII comma in RELRO note comment
- Remove target_link_options(CGE PRIVATE -fPIE -fPIC -pie): these flags are
  inappropriate/redundant for a SHARED library; CMake handles -fPIC automatically
@wysaid wysaid merged commit 4353488 into master Feb 21, 2026
6 of 7 checks passed
@wysaid wysaid deleted the fix/relro-oom-16k-page-size branch February 21, 2026 16:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash: UnsatisfiedLinkError – libCGEExt.so (Out of memory, GNU RELRO)

2 participants