A crash report is two address spaces glued together. Frames in LabSession belong to my Mach-O and symbolicate from my dSYM. Frames in UIKitCore belong to the dyld shared cache and will never appear in nm LabSession. Mixing those up is how people “extract the cache” when they only needed atos and Xcode’s system symbols. This lab is a self-signed simulator build. cryptid=1 stops the lab. I do not dump, decrypt, or ship a dyld shared cache.
Same binary gate as always
1$ file LabSession
2LabSession: Mach-O 64-bit executable arm64
3
4$ otool -l LabSession | egrep 'cmd LC_UUID|uuid |cryptid|LC_CODE|segname __TEXT'
5 cmd LC_SEGMENT_64
6 segname __TEXT
7 cmd LC_ENCRYPTION_INFO_64
8 cryptid 0
9 cmd LC_UUID
10 uuid A1B2C3D4-E5F6-7890-ABCD-EF1234567890
11 cmd LC_CODE_SIGNATURE
cryptid 0. If it is 1, I stop; FairPlay-encrypted __TEXT is not a crash I can symbolicate from this file.
1$ dwarfdump -u LabSession
2UUID: A1B2C3D4-E5F6-7890-ABCD-EF1234567890 (arm64) LabSession
3
4$ dwarfdump -u LabSession.app.dSYM
5UUID: A1B2C3D4-E5F6-7890-ABCD-EF1234567890 (arm64) LabSession
The UUID in LC_UUID, the UUID dwarfdump -u prints on the binary, and the UUID on the dSYM must match. A rebuilt binary with a new UUID will not symbolicate an old .crash even if the source line numbers look close.
1$ class-dump LabSession | sed -n '/LabSession/,+14p'
2@interface LabSession : NSObject
3- (void)startWithToken:(id)token;
4- (void)insecureCopy:(id)token; ; lab crash
5- (void)tapCrash:(id)sender; ; UIButton action
6@end
Why UIKit symbols are not in the app
1$ nm LabSession | egrep 'UIApplication|UIControl|objc_msgSend|insecureCopy'
20000000100001e10 t -[LabSession insecureCopy:]
30000000100001f80 t -[LabSession tapCrash:]
4 U _objc_msgSend
5$ nm LabSession | grep UIKit
6$ otool -L LabSession | grep -i uikit
7 /System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0)
U _objc_msgSend is an undefined symbol. UIKit.framework is a load command, not a copy of UIKit’s __TEXT inside my file. On iOS / the simulator, UIKit’s pages come from the dyld shared cache (one giant mapped image, many frameworks). That is why a crash report shows:
12 UIKitCore 0x000000018b12c4a8 -[UIApplication sendAction:to:from:forEvent:] + 96
and atos -o LabSession on that address is meaningless. The address is not in my Mach-O.
I do not extract the device DSC with third-party dumpers to resolve that frame. Xcode already has DeviceSupport / iOS SDK symbols. symbolicatecrash uses those. Pulling a cache off a phone to “have UIKit locally” is out of scope here and is how people wander into decryption / DRM tooling I will not document.
Crash report excerpt (paths redacted)
Lab: simulator, Apple Silicon, I tapped the UIButton that calls tapCrash: → insecureCopy: with a 36-character stand-in token.
1Incident Identifier: [REDACTED]
2Hardware Model: Mac[REDACTED]
3Process: LabSession [412]
4Path: /Users/[REDACTED]/Library/Developer/CoreSimulator/Devices/[REDACTED]/data/Containers/Bundle/Application/[REDACTED]/LabSession.app/LabSession
5Identifier: com.lab.session
6Version: 1.0 (1)
7Code Type: ARM-64 (Native)
8Parent Process: launchd_sim [REDACTED]
9Date/Time: 2024-08-19 15:02:11.180 +0800
10OS Version: iPhoneSimulator 17.x [REDACTED]
11Exception Type: EXC_BAD_ACCESS (SIGSEGV)
12Exception Subtype: KERN_PROTECTION_FAILURE at 0x[REDACTED]
13Termination Reason: SIGNAL 11 Segmentation fault: 11
14
15Thread 0 Crashed:
160 libsystem_platform.dylib 0x00000001890afc2c _platform_memmove + 204
171 LabSession 0x0000000104a81e38 -[LabSession insecureCopy:] + 0x28
182 LabSession 0x0000000104a81f98 -[LabSession tapCrash:] + 0x18
193 UIKitCore 0x000000018b12c4a8 -[UIApplication sendAction:to:from:forEvent:] + 96
204 UIKitCore 0x000000018b12c5f0 -[UIControl sendAction:to:forEvent:] + 128
215 UIKitCore 0x000000018b12c8a4 -[UIControl _sendActionsForEvents:withEvent:] + 352
22
23Binary Images:
240x104a80000 - 0x104a87fff LabSession arm64 <a1b2c3d4e5f67890abcdef1234567890> /Users/[REDACTED]/Library/Developer/CoreSimulator/Devices/[REDACTED]/data/Containers/Bundle/Application/[REDACTED]/LabSession.app/LabSession
250x180000000 - 0x18fffffff dyld shared cache arm64 <[REDACTED]>
Frame 1–2 are mine. Frames 3–5 are the shared cache. Binary Images gives me the load address 0x104a80000 and the UUID a1b2c3d4… that must match dwarfdump -u.
atos on the lab frames
File-unslid __TEXT vmaddr is 0x100000000 (otool -l). Load address in the report is 0x104a80000. Slide = 0x4a80000.
1$ xcrun atos -o LabSession.app.dSYM/Contents/Resources/DWARF/LabSession \
2 -arch arm64 -l 0x104a80000 \
3 0x104a81e38 0x104a81f98
4-[LabSession insecureCopy:] (in LabSession) (LabSession.m:41)
5-[LabSession tapCrash:] (in LabSession) (LabSession.m:49)
Same addresses through lldb after I reproduce under the debugger (no report needed):
1(lldb) image list LabSession
2[ 0] A1B2C3D4-E5F6-7890-ABCD-EF1234567890 0x0000000104a80000 LabSession
3(lldb) image lookup -v -a 0x104a81e38
4 Address: LabSession[0x0000000100001e38] (LabSession.__TEXT.__text + 0x238)
5 Summary: LabSession`-[LabSession insecureCopy:] + 40 at LabSession.m:41
6(lldb) # UIKit address from the report — not in this image:
7(lldb) image lookup -a 0x18b12c4a8
8 Address: UIKitCore[0x000000018b12c4a8]
9 Summary: UIKitCore`-[UIApplication sendAction:to:from:forEvent:] + 96
image lookup on the UIKit address works in a live simulator process because dyld already mapped the cache. It does not work against the on-disk LabSession file. That is the whole lesson.
For a .crash file I do not have a live process for:
1$ export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
2$ xcrun symbolicatecrash LabSession.crash > LabSession.crash.symbolicated
symbolicatecrash matches UUID → dSYM (Spotlight / dwarfdump) for my frames, and UUID → Xcode iOS SDK symbols for UIKit. I do not pass a hand-extracted DSC.
ARM64 at the crashing IMP
1; otool -tV LabSession file VA, slide 0
2; -[LabSession insecureCopy:]
30000000100001e10 pacibsp
40000000100001e14 stp x29, x30, [sp, #-0x30]!
50000000100001e18 mov x29, sp
60000000100001e1c stp x20, x19, [sp, #0x10]
70000000100001e20 sub sp, sp, #0x10 ; char buf[16]
80000000100001e24 mov x19, x2 ; NSString * token
90000000100001e28 mov x0, x19
100000000100001e2c bl 0x1000024a0 ; -[NSString UTF8String]
110000000100001e30 add x8, x29, #0x18 ; &buf
120000000100001e34 mov x1, x0
130000000100001e38 bl 0x1000024c4 ; _memcpy ← crash pc + 0x28 from start
Report said insecureCopy: + 0x28. 0x100001e10 + 0x28 = 0x100001e38, which is the bl memcpy. That is the line atos named LabSession.m:41.
Sanitized reproduction
I paste a 36-character stand-in lab_ + 'A'*32. I log length, not the token.
1(lldb) breakpoint set -n '-[LabSession insecureCopy:]'
2(lldb) po [$x2 length]
336
4(lldb) memory read -c 8 $x2
5; skip — NSString object header is not the bytes. UTF8:
6(lldb) p (char *)[(NSString *)$x2 UTF8String]
7(char *) $1 = 0x0000000283bb4a00 "lab_AAAA"...
8(lldb) # remaining 28 bytes not copied into the note
ASAN rebuild of the same file:
1==412==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x...
2WRITE of size 37 at ... thread T0
3 #0 memcpy
4 #1 -[LabSession insecureCopy:] LabSession.m:41
5 #2 -[LabSession tapCrash:] LabSession.m:49
6 #3 -[UIApplication sendAction:to:from:forEvent:]
7Shadow bytes around the buggy address:
8 00 00 00 00[f1]f1 f1 f1 00 00[f3]f3
Source of the lab bug:
1- (void)insecureCopy:(NSString *)token {
2 char buf[16];
3 const char *u = token.UTF8String;
4 memcpy(buf, u, strlen(u) + 1); // no bound
5 _scratch = buf[0];
6}
Repro is: 36-byte UTF-8, 16-byte buffer, memcpy size 37, pc insecureCopy:+0x28, UUID-matched atos line LabSession.m:41, UIKit frames left to symbolicatecrash. Not a DSC dump, not FairPlay, not a jailbreak.
Closing
dwarfdump -u ↔ LC_UUID ↔ crash Binary Images is the join key. atos -l <load address> resolves my frames from my dSYM. UIKit lives in the dyld shared cache; nm LabSession will never grow those symbols. Xcode’s symbolicatecrash is the supported path for system frames. Extracting the cache off a device is not.
Commands appendix
1otool -l LabSession | egrep 'cryptid|LC_UUID|uuid '
2dwarfdump -u LabSession
3dwarfdump -u LabSession.app.dSYM
4nm LabSession | egrep 'insecureCopy|UIApplication|objc_msgSend'
5class-dump LabSession
6xcrun atos -o LabSession.app.dSYM/Contents/Resources/DWARF/LabSession -arch arm64 -l 0x104a80000 0x104a81e38
7xcrun symbolicatecrash LabSession.crash
8xcrun lldb ./LabSession