Skip to content

fix(objc): box resilient value types to fix missing x86_64 symbols#8037

Merged
itaybre merged 9 commits into
mainfrom
fix/sentryobjc-x86-64-missing-symbols
Jun 11, 2026
Merged

fix(objc): box resilient value types to fix missing x86_64 symbols#8037
itaybre merged 9 commits into
mainfrom
fix/sentryobjc-x86-64-missing-symbols

Conversation

@itaybre

@itaybre itaybre commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes #8034 — SentryObjC dynamic framework is missing _OBJC_CLASS_$_ symbols for 4 classes in the x86_64 architecture slice:

  • SentryObjCAttributeContent
  • SentryObjCUnit
  • SentryObjCMetric
  • SentryObjCMetricValue

Root cause

These 4 wrapper classes in SentryObjCCompat store properties of pure Swift value types (SentryAttributeContent, SentryUnit, SentryMetricValue, SentryMetric) from the SentrySwift module.

When building with BUILD_LIBRARY_FOR_DISTRIBUTION=YES, the Swift compiler treats SentrySwift types as resilient — their in-memory size is unknown at compile time. On x86_64, this causes the compiler to generate a "class metadata template" (CMt) for runtime class realization instead of emitting a static _OBJC_CLASS_$_ linker symbol. Consumers then get undefined symbol errors at link time.

On arm64, the compiler emits a statically-laid-out class, so the issue only manifests on x86_64.

The other 41 working wrapper classes all wrap ObjC classes (pointer-sized, always known layout), which is why they aren't affected.

Fix

Wrap the resilient stored properties in a Box<T> indirection class (new file: Box.swift). This makes the ivar pointer-sized (always known at compile time), so the compiler emits a static class layout on all architectures. The box adds one heap allocation per wrapper instance, which is negligible since these are already NSObject subclasses.

Verification

Built SentryObjC for macOS Release with BUILD_LIBRARY_FOR_DISTRIBUTION=YES and confirmed via nm that all 4 _OBJC_CLASS_$_ symbols are now present in both arm64 and x86_64 object files, with no CMt (class metadata template) symbols.

Without @Frozen, the Swift compiler treats these types as resilient
on x86_64 under -enable-library-evolution (BUILD_LIBRARY_FOR_DISTRIBUTION).
This causes the compiler to use runtime class realization (CMt) instead
of emitting a static _OBJC_CLASS_$_ symbol, which results in linker
failures for consumers of the SentryObjC dynamic framework.

Fixes #8034
@itaybre itaybre added the ready-to-merge Use this label to trigger all PR workflows label Jun 11, 2026
@sentry

sentry Bot commented Jun 11, 2026

Copy link
Copy Markdown

📲 Install Builds

iOS

🔗 App Name App ID Version Configuration
SDK-Size io.sentry.sample.SDK-Size 9.17.0 (1) Release

⚙️ sentry-cocoa Build Distribution Settings

@codecov

codecov Bot commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.29730% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 87.313%. Comparing base (089f6f4) to head (f959825).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
Sources/SentryObjCCompat/SentryObjCOptions.swift 0.000% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##              main     #8037       +/-   ##
=============================================
- Coverage   87.333%   87.313%   -0.021%     
=============================================
  Files          553       554        +1     
  Lines        31983     31987        +4     
  Branches     13158     13159        +1     
=============================================
- Hits         27932     27929        -3     
- Misses        4004      4010        +6     
- Partials        47        48        +1     
Files with missing lines Coverage Δ
Sources/SentryObjCCompat/Box.swift 100.000% <100.000%> (ø)
.../SentryObjCCompat/SentryObjCAttributeContent.swift 100.000% <100.000%> (ø)
Sources/SentryObjCCompat/SentryObjCMetric.swift 100.000% <100.000%> (ø)
...urces/SentryObjCCompat/SentryObjCMetricValue.swift 100.000% <100.000%> (ø)
Sources/SentryObjCCompat/SentryObjCUnit.swift 100.000% <100.000%> (ø)
Sources/SentryObjCCompat/SentryObjCOptions.swift 92.380% <0.000%> (ø)

... and 6 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 089f6f4...f959825. Read the comment docs.

Under -enable-library-evolution (BUILD_LIBRARY_FOR_DISTRIBUTION), the
Swift compiler treats cross-module value types as resilient — their size
is unknown at compile time. On x86_64, this forces the compiler to use
runtime class realization (CMt) instead of emitting a static
_OBJC_CLASS_$_ symbol, causing linker failures for consumers.

Wrapping the resilient stored properties in a Box<T> class makes the
ivar pointer-sized (always known), so the compiler emits a static class
layout on all architectures.

Affected wrappers: SentryObjCAttributeContent, SentryObjCUnit,
SentryObjCMetricValue, SentryObjCMetric.

Fixes #8034
@itaybre itaybre changed the title fix(objc): add @frozen to fix missing x86_64 symbols fix(objc): box resilient value types to fix missing x86_64 symbols Jun 11, 2026
The internal property was renamed during the boxing refactor.
@itaybre itaybre marked this pull request as ready for review June 11, 2026 03:06
@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1226.27 ms 1262.07 ms 35.80 ms
Size 24.14 KiB 1.18 MiB 1.15 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
6c64f68 1235.80 ms 1272.35 ms 36.55 ms
ccf353a 1233.79 ms 1268.77 ms 34.98 ms
58e87fd 1234.27 ms 1262.09 ms 27.82 ms
9da166b 1222.40 ms 1250.24 ms 27.84 ms
adef457 1229.45 ms 1262.67 ms 33.22 ms
5e4d0a6 1230.40 ms 1255.44 ms 25.04 ms
ffb6adc 1218.60 ms 1247.47 ms 28.87 ms
09627e8 1223.68 ms 1261.95 ms 38.27 ms
bdd8e0e 1233.35 ms 1266.96 ms 33.60 ms
e3147fd 1227.15 ms 1257.79 ms 30.63 ms

App size

Revision Plain With Sentry Diff
6c64f68 24.14 KiB 1.17 MiB 1.14 MiB
ccf353a 24.14 KiB 1.17 MiB 1.15 MiB
58e87fd 24.14 KiB 1.17 MiB 1.14 MiB
9da166b 24.14 KiB 1.16 MiB 1.14 MiB
adef457 24.14 KiB 1.15 MiB 1.13 MiB
5e4d0a6 24.14 KiB 1.17 MiB 1.15 MiB
ffb6adc 24.14 KiB 1.15 MiB 1.12 MiB
09627e8 24.14 KiB 1.17 MiB 1.14 MiB
bdd8e0e 24.14 KiB 1.16 MiB 1.13 MiB
e3147fd 24.14 KiB 1.17 MiB 1.14 MiB

Previous results on branch: fix/sentryobjc-x86-64-missing-symbols

Startup times

Revision Plain With Sentry Diff
e1a48a6 1218.70 ms 1255.69 ms 36.99 ms

App size

Revision Plain With Sentry Diff
e1a48a6 24.14 KiB 1.18 MiB 1.15 MiB

@philprime philprime left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, but we will have to expand this to other types as well when we start to refactor the underlying SDK to use Swift-only classes or even Swift data structures. I'll create a script to detect a drift between architectures in a follow-up PR

Add validate-xcframework-symbols.sh that compares ObjC class symbols
across architectures within fat binaries. Detects when resilient value
types cause symbols to be emitted on arm64 but missing on x86_64.

Wired into all XCFramework validation points: local builds, CI
assembly workflows, and release validation.
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code can easily blow up and is hard to test. We had severe bugs in the past. Be extra careful when changing these files, and have an extra careful look at these:

  • .github/file-filters.yml

@itaybre itaybre enabled auto-merge (squash) June 11, 2026 13:19
@itaybre itaybre merged commit 9787f05 into main Jun 11, 2026
282 of 286 checks passed
@itaybre itaybre deleted the fix/sentryobjc-x86-64-missing-symbols branch June 11, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Use this label to trigger all PR workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SentryObjC dynamic package is missing several symbols in x86_64 arch

2 participants