fix(error-tracking): correct frame addresses, ordering, and in-app detection#549
Open
fix(error-tracking): correct frame addresses, ordering, and in-app detection#549
Conversation
…tection Four correctness fixes for iOS stack trace capture: - Zero-pad instruction addresses to 16 hex digits (0x%016llx) so the format is consistent and cymbal can always parse them reliably. - Strip PAC bits from arm64e pointers (mask 0x0000_000f_ffff_ffff) before storing addresses. Modern iPhones embed pointer authentication codes in the high bits; without stripping, dladdr lookups and cymbal symbolication fail or produce wrong results. - Reverse frames to bottom-up order (outermost/main first, crash site last) in both PostHogExceptionProcessor and PostHogCrashReportProcessor. callStackReturnAddresses and PLCrashReport both deliver frames top-down; the Sentry event format (which cymbal consumes) expects bottom-up. - Add isSystemPath() helper to PostHogStackTraceProcessor to catch system binaries not in the hardcoded module-name list (e.g. private frameworks like 'Gestures', 'Accessibility' from UIKitCore) by checking their binary path against /System/ and /usr/lib/ prefixes. Pass package path to isInApp() so the path check is applied.
ioannisj
approved these changes
Apr 3, 2026
…ked in-app Two complementary fixes for frames that dladdr cannot resolve to a path: 1. When dladdr succeeds but dli_fname is nil (e.g. shared-cache private frameworks like Gestures/UIKitCore on Simulator, or on-device dyld shared cache binaries), inApp now defaults to false instead of falling through to inAppByDefault=true. We have no evidence that a frame with no resolvable binary path is user code. 2. Extend systemPrefixes with known private UIKit sub-frameworks (Gestures, UIKitCore, Accessibility, UpdateCycle, TextInput, etc.) and common system dylibs (libobjc, dyld, libsystem_c, etc.) so that frames from these modules are rejected by isSystemFramework() even when dladdr does return a path.
Contributor
posthog-ios Compliance ReportDate: 2026-04-03 17:34:24 UTC ✅ All Tests Passed!0/0 tests passed |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Four correctness fixes for iOS stack trace capture.
Fixes
Zero-padded addresses
Instruction addresses are now formatted as 16-digit zero-padded hex (
0x%016llx), consistent with what cymbal expects for address lookup.PAC bit stripping (arm64e)
Modern iPhones embed pointer authentication codes in the high bits of pointers. Addresses are now masked with
0x0000_000f_ffff_ffffbefore being stored, sodladdrlookups and cymbal symbolication work correctly on arm64e devices.Frame ordering
Both
PostHogExceptionProcessorandPostHogCrashReportProcessorwere emitting frames in top-down order (crash site first). The Sentry event format that cymbal consumes expects bottom-up (outermost/main first, crash site last). Frames are now reversed before serialization.System path detection
isInApp()was only checking a hardcoded list of module names for system frameworks. Private frameworks not in that list (e.g.Gestures,Accessibilityfrom UIKitCore) were incorrectly marked as in-app. A newisSystemPath()helper checks the binary path against/System/and/usr/lib/prefixes, covering both device and Simulator paths.