Skip to content

fix(runtime): resolve system symbols when an iOS app runs on a Mac - #549

Open
NathanWalker wants to merge 1 commit into
mainfrom
fix/symbol-loader-ios-on-mac
Open

NathanWalker wants to merge 1 commit into
mainfrom
fix/symbol-loader-ios-on-mac

Conversation

@NathanWalker

@NathanWalker NathanWalker commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Summary

An iOS app running on an Apple Silicon Mac ("Designed for iPad") crashes at boot, before any app code runs:

ReferenceError: UIApplicationDidFinishLaunchingNotification is not defined
    at new iOSApplication (@nativescript/core)

On device builds, SymbolLoader opens system frameworks at /System/Library/Frameworks/<Name>.framework. On a Mac, CFBundleCreate succeeds for that path, but UIKit's symbols live in the loaded /System/iOSSupport images. So the bundle lookup returns NULL, and the loader returned that NULL without trying anything else.

 SymbolLoader::loadFunctionSymbol / loadDataSymbol
   if resolver = resolveModule(module)
-    return resolver->load…Symbol(name)
+    if symbol = resolver->load…Symbol(name)
+      return symbol
   return dlsym(RTLD_DEFAULT, name)

Evidence

Checked in lldb inside the running Mac app (macOS 26.6.2, Xcode 27.1, @nativescript/ios 9.1.0):

CFBundleCreate(/System/Library/Frameworks/UIKit.framework)        -> non-NULL bundle
CFBundleGetDataPointerForName(that bundle, "UIApplicationDid…")    -> 0x0
dlsym(RTLD_DEFAULT, "UIApplicationDidFinishLaunchingNotification") -> 0x1efc2f990
[NSBundle bundleForClass:UIApplication].bundlePath -> /System/iOSSupport/System/Library/PrivateFrameworks/UIKitCore.framework
  • Before: an Angular + @nativescript/canvas app built for "My Mac (Designed for iPad)" aborts in tns::Runtime::RunMainScript with the ReferenceError above.
    After: with this commit's runtime swapped into the same build, the app launches and renders its full UI on the Mac.

Merge Danger

Door: two-way

Blast Radius: small

The fallback only runs when a module's resolver returns NULL, which was a hard failure before (an undefined constant or uncallable function). Symbols that resolved before still resolve the same way. On a real iOS device or simulator, a symbol that's missing from its own framework could now be found in another loaded image with the same name. That's the same lookup a module-less symbol already gets.

Summary by CodeRabbit

  • Bug Fixes
    • Improved compatibility when loading framework functionality in iOS apps running on a Mac, including cases where the primary lookup cannot find a symbol. This helps affected app functionality continue to load instead of failing at that lookup.

On Apple Silicon Macs ("Designed for iPad"), SymbolLoader opens system
frameworks at /System/Library/Frameworks. CFBundleCreate succeeds there,
but UIKit's symbols live under /System/iOSSupport, so the bundle lookup
returns NULL and the loader returned it without trying anything else.
@nativescript/core then failed at boot with "ReferenceError:
UIApplicationDidFinishLaunchingNotification is not defined".

A miss from the module's resolver now falls back to dlsym(RTLD_DEFAULT),
which finds the loaded iOSSupport images.
@coderabbitai

coderabbitai Bot commented Nov 7, 2026 •

Copy link
Copy Markdown

Explain Change →

Walkthrough

Both symbol-loading methods now use dlsym(RTLD_DEFAULT, symbolName) when the module resolver is missing or returns null. A comment describes a framework-symbol lookup case on an iOS app running on a Mac.

Changes: Symbol lookup

Layer / File(s) Summary
Resolver fallback
NativeScript/runtime/SymbolLoader.mm
loadFunctionSymbol and loadDataSymbol fall back to process-wide dlsym when the module resolver is missing or returns null.

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix

Suggested reviewers: darind

Merge Risk: Minimal · up to 84e11

The change lets iOS apps on Apple Silicon Macs find system framework symbols that live in iOSSupport images, so they no longer fail at boot. The remaining concern is a theoretical symbol-name collision with a narrow practical chance of occurring, and it does not block merging.

Pre-merge checks: Passed 5

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title names the main change: SymbolLoader now resolves system symbols through a dlsym fallback when an iOS app runs on a Mac. The raw summary confirms that loadFunctionSymbol and loadDataSymbol fa…
Docstring Coverage Passed No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the main change: SymbolLoader now resolves system symbols through a dlsym fallback when an iOS app runs on a Mac. The raw summary confirms that loadFunctionSymbol and loadDataSymbol fall through to dlsym(RTLD_DEFAULT) when the module resolver misses. The objectives describe the same fix for UIKit symbols in /System/iOSSupport images. The title is specific, follows the conventional commit style, and is under 72 characters.

Full details: Docstring Coverage

Explanation

No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

A rabbit checked the symbols at night,
The resolver had no name in sight.
So dlsym searched the wider field,
And found the symbol it could yield.
The rabbit hopped beneath the moon,
Then tucked its notes away till noon.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Additional comments: 1

NativeScript/runtime/SymbolLoader.mm-149-149: 1

149-149: Major · Data Integrity & Integration · Heavy lift

Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

Restrict fallback results to the intended module.

If the module resolver misses and another loaded image exports symbolName, dlsym(RTLD_DEFAULT, symbolName) can return that image’s symbol. The callers then use the address as the requested module’s function or data. An incompatible function can be called, or unrelated memory can be read as data. Limit this fallback to the iOS-on-Mac system-framework case and verify the returned symbol’s image before accepting it. Apple documents that RTLD_DEFAULT returns the first matching symbol in its process-wide search scope. (developer.apple.com)

Also applies to: 159-159

Review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1e2d1e66-5fe8-45e9-bdba-a2d7f1f5bcc1
Commits

Reviewing files that changed from the base of the PR and between 5a186cf and 84e1187.

Files selected for processing: 1

  • NativeScript/runtime/SymbolLoader.mm

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 1 remain after this review.

This branch has not been deployed

No deployments
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.

1 participant