Repository navigation
cmux NEXT: hide the app executable's exports, keep names in an in-app symbol map (-11 MiB, cx-b6r7) - #20762
Conversation
cmux NEXT's executable will link with -no_exported_symbols, and the release strip then removes every name from it. Expect the strip to write Contents/Resources/cmux-symbols.bin first (per slice: LC_UUID and the __TEXT,__text functions as offsets), and a second strip pass over the stripped executable to keep it. Runs in the cmux-next checks job. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
…b6r7) Link the cmux-next Release executable with -no_exported_symbols: nothing resolves its symbols at runtime, and its 110,746 exports cost about 11.5 MiB (export trie, symbol and string tables) once the release strip can drop them. So nobody reads raw offsets, the release strip first writes Contents/Resources/cmux-symbols.bin (scripts/write-app-symbol-map.py): per slice, the LC_UUID and the __TEXT,__text functions as offsets, raw DEFLATE. StackSymbolicator names app-executable frames through it (AppSymbolMap) and other images through dladdr; hang records and uncaught exception traces (now from callStackReturnAddresses) both use it. A frame with no name keeps its image offset for the dSYM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
all web/size checks green |
|
Not verified: macOS jobs did not run: compile and app tests were skipped on CI passes on Written by |
…rt (cx-b6r7) Xcode refuses -no_exported_symbols in OTHER_LDFLAGS and wants its own setting, LD_EXPORT_SYMBOLS = NO (cmux-next Release). AppSymbolMap's public init takes Data and UUID, so it needs public import Foundation. Both from the exact-head fleet Release build (exit 65). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
The crash ratchet counted AppSymbolMap's byte subscripts and integer conversions (26 index_subscript, 8 int_conversion in CmuxNextControl). Read the file through a small cursor that returns nil past the end, with checked subscripts and truncatingIfNeeded conversions: a damaged map gives no names instead of a trap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (cx-b6r7) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…b6r7) The nightly strips twice. After the first pass, __mh_execute_header is still in __TEXT,__text, so the second pass rewrote the map with that one name under the same UUID. Leave the map alone when it already has every slice UUID of the executable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
cmux-next tour of Path-selected interactions
Core UI (before): 12 ok
Screenshots (11)1. Launch
Screenshots (11)1. Launch Tours are data in |
























Summary
cmux NEXT's main executable exports all 110,746 of its symbols. The export trie (2.9 MiB), symbol table (1.8 MiB) and string table (6.8 MiB) take about 11.5 MiB of the installed app, and nothing looks them up at runtime. An audit found:
-bundle_loaderplug-ins or test hosts in the app;dlsymcalls only into system libraries, CEF and the shim;Leo approved hiding them, on one condition: nobody reads raw offsets.
-Xlinker -no_exported_symbols. Debug (DEV) is unchanged. The Linux builder mirrors the flag from the pbxproj (cmuxterm-hq#2100).nightly-next-linux/deploy.sh). Until then nothing changes: the exports stay, and the map is written alongside them.scripts/strip-release-bundle.shrunsscripts/write-app-symbol-map.py. It writesContents/Resources/cmux-symbols.bin: for each slice, theLC_UUIDand the__TEXT,__textfunctions as offsets, compressed with raw DEFLATE. A second strip pass over the stripped executable keeps the map.StackSymbolicatornames frames in the app executable through the map (AppSymbolMap, only the running slice is loaded), and frames in other images throughdladdras before.debug.hangs) and uncaught exception traces (now read fromcallStackReturnAddresses, which feed the next launch's crash notice and issue report) both use it.cmuxexecutablecmux-symbols.bin(arm64 slice)Net: about −8.6 MiB installed for the arm64 nightly. The universal Release executable from this head strips to 189,379,088 bytes (arm64 slice 91,812,368), and its universal map is 5.1 MiB (447,385 functions over two slices).
Sample trace. Below is a
sampleof the stripped Release app from this head, on a capture Mac.sampleprinted??? (in cmux)for every app frame. The same offsets, resolved through the shipped map byAppSymbolMap, give these frames, and the per-function offsets matchatosagainst the dSYM:Ghostty's internal (Zig) functions have no symbols even today, so they still resolve to the nearest Ghostty export (for example
ghostty_surface_new + 255408), the same as before this change. Their image offset is kept for dSYM lookup.Verification
cmux-symbols.binmissing.check-release-compile.shpassed on the merged head 9b10dd2 (fleet step 0c4e8ad3b304, xcodebuild exit 0).Review
A correctness review subagent covered this PR and cmuxterm-hq#2100.
__mh_execute_header). The map now stays when it already covers the executable's UUIDs. The test failed before the fix and passes after it.__text, so stubs are not named after the last function;address - 1for frames after the first;Changelog
Changed: cmux NEXT takes about 11 MB less disk space (the app executable no longer carries its symbol names; hang and crash traces still name app functions).
🤖 Generated with Claude Code