Skip to content

Flag lmdb text_env as code so Debug iOS links - #9

Merged
j0ntz merged 1 commit into
mainfrom
jon/monero-text-env-link
Sep 22, 2026
Merged

j0ntz merged 1 commit into
mainfrom
jon/monero-text-env-link

Conversation

@j0ntz

@j0ntz j0ntz commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Technical Design Document

lmdb-text-env-arm64-debug-link.md

Description

A Debug iOS simulator build of edge-react-gui carrying all four large native wallet libraries (react-native-pirate-wallet, react-native-zcash, react-native-monero, react-native-zano) fails to link:

ld: warning: symbols in __TEXT,text_env (libmonero-module.a[arm64][2](monero-module.o))
    have unwind information, but it's not a code section
    (missing 'regular,pure_instructions' section flag)
ld: fixup error (kind=arm64_b26) at '__ZN5boost6chrono12system_clock3nowEv'+0x450994
    from libmonero-module.a[arm64][2](monero-module.o), B/BL out of range
    (displacement=177426652, max is +/-128MB), from 0x00473394 to 0x0ADA8470 ('_mdb_mutex_failed')

The LMDB vendored inside monero puts about 50 rarely used environment functions in a private section through its ESECT macro, which on Apple expands to __attribute__((section("__TEXT,text_env"))). That two-field Mach-O specifier leaves S_ATTR_PURE_INSTRUCTIONS unset, so ld does not count the section as code: it sorts it past every real code section (173MB into a 190MB __TEXT) and will not plant a branch island for a call that crosses the +/-128MB B/BL reach. Release links only because its __TEXT is about 50MB smaller.

This spells the section out in full, so text_env carries the same flags as __text and ld sorts it directly after __text. The section survives, so upstream's grouping of cold environment functions still holds.

Two supporting pieces come with it:

  • An anchor assertion. String.replace no-ops when the pattern misses, so a drifted monero would silently produce an unpatched module and a link that fails again for a reason nobody would connect to this change. The throw turns that into a build failure naming the patch, matching the existing rpc.cpp patch in the same file.
  • A patch revision in the monero.clone cacheTag (1-esect). The tag does not hash the patch text, so on a cache hit monero.clone is skipped outright and the tree keeps whatever the previous run left in it; bumping the leading revision digit is what makes an edited patch rebuild.

Asana: Monero: fix iOS debug build linking

Testing

All measurements on 2026-09-07 against edge-react-gui at f15eb640 (branch agent/1214721783909451, react-native-pirate-wallet 0.3.4), untrimmed (zcash, monero and zano all autolinked), on an iOS 18.6 simulator.

  1. Compile probe for arm64-apple-ios-simulator: the two-field section spelling gives section flags 0x00000400; the four-field spelling gives 0x80000400, adding S_ATTR_PURE_INSTRUCTIONS, which is what __text carries.
  2. otool -l over the rebuilt MoneroModule.xcframework: text_env carries 0x80000400 on ios-arm64 and on both simulator architectures. The published 0.4.2 artifact carries 0x00000000.
  3. Two Debug simulator links over the same DerivedData, differing only in which framework sat in node_modules/react-native-monero/ios/:
    • published 0.4.2: ** BUILD FAILED ** with the arm64_b26 error above, reproducing the report exactly.
    • rebuilt: ** BUILD SUCCEEDED **, zero arm64_b26 lines and zero text_env lines. text_env moved from 0x00ada62e0 to 0x005f6e5b8, directly after __text, so no branch island is needed at all.
  4. The linked app installed, launched and rendered its wallet list with Monero, Zano and the rest of the plugins live.
  5. On edge-rjqa3, wallet "My Monero" synced to 0.001891391795 XMR ($0.97).
  6. From that wallet, 0.000484 XMR (fee 0.00017752 XMR) to "My Monero 3" reached the "Transaction Success" confirmation, so createTransaction and broadcastTransaction both ran against the rebuilt module.

verify-repo.sh passes (changelog, prepare, eslint).

Not done here: the version commit and publish (this repo cuts the version as its own commit at publish time), then the edge-react-gui pin bump from 0.5.0 to the new version. That bump is a pin change only: develop and edge-currency-accountbased master already consume 0.5.0.

Cases 4-6 above ran the pirate branch's 0.4.2 JavaScript against the rebuilt native module. That is safe because the compiled MoneroEngine.broadcastTx in that branch's node_modules discards broadcastTransaction's return value, the only surface 0.5.0 changed.

Test evidence

5a2411f
Flag lmdb text_env as code so Debug iOS links

untrimmed debug build launched

xmr wallet synced

xmr send transaction success

Note

Medium Risk
Changes native monero/LMDB compile output and iOS linking layout; wrong or stale patches could break builds or regress Debug links, though runtime LMDB semantics are unchanged.

Overview
Fixes Debug iOS simulator link failures (arm64_b26 / _mdb_mutex_failed) when the app bundles several large native wallet libraries. Vendored LMDB’s Apple ESECT macro used a two-field Mach-O section name, so __TEXT,text_env was not treated as code and landed ~173MB into __TEXT, beyond arm64 B/BL reach.

During monero.clone in scripts/libraries/lwsf.ts, the patch rewrites mdb.c to use a full section specifier (regular,pure_instructions), matching __text so the linker lays text_env with other code. A failed anchor check aborts the build if upstream mdb.c drifts, and moneroPatchTag is appended to the clone cacheTag so edited patches are not served from a stale cached tree.

CHANGELOG records the fix; src/docs/lmdb-text-env-arm64-debug-link.md documents problem, design, and verification. No JS or wallet API changes; rebuilt MoneroModule.xcframework only.

Reviewed by Cursor Bugbot for commit 3e86c2c. Bugbot is set up for automated code reviews on this repo. Configure here.

@j0ntz
j0ntz marked this pull request as ready for review September 7, 2026 23:33
@j0ntz
j0ntz force-pushed the jon/monero-text-env-link branch 2 times, most recently from 650953e to 5a2411f Compare September 8, 2026 18:37

@peachbits peachbits left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The mechanism checks out: the anchor matches the pinned mdb.c exactly once, all 52 ESECT symbols are functions so pure_instructions is accurate, and the moneroPatchTag bump does force lwsf.build.* to recompile through the dirty-dep cascade in scripts/utils/tasks.ts. No correctness findings. The four notes below are housekeeping.

Comment thread src/docs/lmdb-text-env-arm64-debug-link.md
Comment thread src/docs/lmdb-text-env-arm64-debug-link.md Outdated
Comment thread src/docs/lmdb-text-env-arm64-debug-link.md Outdated
Comment thread scripts/libraries/lwsf.ts Outdated

@peachbits peachbits left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

housekeeping items worth addressing before merging

@j0ntz

j0ntz commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

All four housekeeping threads are fixed and resolved: the Related row now points at the merge commit of accountbased#1055 with the anchor that exists there, both code permalinks are repo-relative, the arm64_b26 link label is closed, and the cacheTag comment states the real mechanism with the tag bumped to 1-esect. verify-repo passed on the branch (changelog, prepare, eslint).

The vendored LMDB in monero puts its infrequently used env functions in a
private __TEXT,text_env section. The two-field Mach-O section spec leaves
S_ATTR_PURE_INSTRUCTIONS unset, so ld does not treat the section as code:
it sorts it past every real code section and will not plant a branch island
into it. A Debug simulator build carrying all four large native wallet
libraries pushes __TEXT to ~190MB, which puts text_env beyond the +/-128MB
reach of arm64 B/BL, and the link fails on an arm64_b26 fixup error against
_mdb_mutex_failed. Release links only because its __TEXT is ~50MB smaller.

Patch the section spec to its full form so the section carries the same
flags as __text. The section survives, so upstream's grouping still holds.
The patch asserts its own anchor and the clone cacheTag now carries a patch
revision, since getRepo checks the tree out fresh on every cache miss.
@j0ntz
j0ntz force-pushed the jon/monero-text-env-link branch from 5a2411f to 3e86c2c Compare September 22, 2026 22:14
@j0ntz
j0ntz merged commit db35222 into main Sep 22, 2026
2 checks passed
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.

2 participants