From 7ad621268abcc4beb7a2abae1be19c7c09c253ce Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Tue, 19 Oct 2021 12:01:19 +0100 Subject: [PATCH] Use Function Starts data for symbolication --- Bugsnag.xcodeproj/project.pbxproj | 42 +++-- .../KSCrash/Recording/BSG_KSCrashReport.c | 48 +++--- .../KSCrash/Recording/BSG_KSSystemInfo.m | 3 +- .../Recording/Tools/BSG_KSArchSpecific.h | 6 - .../KSCrash/Recording/Tools/BSG_KSBacktrace.c | 7 +- .../KSCrash/Recording/Tools/BSG_KSBacktrace.h | 5 +- .../Recording/Tools/BSG_KSDynamicLinker.c | 109 ------------- .../Recording/Tools/BSG_KSDynamicLinker.h | 59 ------- .../Recording/Tools/BSG_KSMachHeaders.c | 27 ---- .../Recording/Tools/BSG_KSMachHeaders.h | 9 -- .../KSCrash/Recording/Tools/BSG_Symbolicate.c | 153 ++++++++++++++++++ .../KSCrash/Recording/Tools/BSG_Symbolicate.h | 30 ++++ Bugsnag/Payload/BugsnagStackframe.m | 22 +-- Tests/BugsnagStackframeTest.m | 12 +- 14 files changed, 255 insertions(+), 277 deletions(-) delete mode 100644 Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSDynamicLinker.c delete mode 100644 Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSDynamicLinker.h create mode 100644 Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c create mode 100644 Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.h diff --git a/Bugsnag.xcodeproj/project.pbxproj b/Bugsnag.xcodeproj/project.pbxproj index 1b98d4f55..9e0e96918 100644 --- a/Bugsnag.xcodeproj/project.pbxproj +++ b/Bugsnag.xcodeproj/project.pbxproj @@ -374,9 +374,6 @@ 008969602486DAD000DC48C2 /* BSG_KSSysCtl.h in Headers */ = {isa = PBXBuildFile; fileRef = 008969042486DAD000DC48C2 /* BSG_KSSysCtl.h */; }; 008969612486DAD000DC48C2 /* BSG_KSSysCtl.h in Headers */ = {isa = PBXBuildFile; fileRef = 008969042486DAD000DC48C2 /* BSG_KSSysCtl.h */; }; 008969622486DAD000DC48C2 /* BSG_KSSysCtl.h in Headers */ = {isa = PBXBuildFile; fileRef = 008969042486DAD000DC48C2 /* BSG_KSSysCtl.h */; }; - 008969662486DAD000DC48C2 /* BSG_KSDynamicLinker.c in Sources */ = {isa = PBXBuildFile; fileRef = 008969062486DAD000DC48C2 /* BSG_KSDynamicLinker.c */; }; - 008969672486DAD000DC48C2 /* BSG_KSDynamicLinker.c in Sources */ = {isa = PBXBuildFile; fileRef = 008969062486DAD000DC48C2 /* BSG_KSDynamicLinker.c */; }; - 008969682486DAD000DC48C2 /* BSG_KSDynamicLinker.c in Sources */ = {isa = PBXBuildFile; fileRef = 008969062486DAD000DC48C2 /* BSG_KSDynamicLinker.c */; }; 008969692486DAD000DC48C2 /* BSG_KSMach_Arm.c in Sources */ = {isa = PBXBuildFile; fileRef = 008969072486DAD000DC48C2 /* BSG_KSMach_Arm.c */; }; 0089696A2486DAD000DC48C2 /* BSG_KSMach_Arm.c in Sources */ = {isa = PBXBuildFile; fileRef = 008969072486DAD000DC48C2 /* BSG_KSMach_Arm.c */; }; 0089696B2486DAD000DC48C2 /* BSG_KSMach_Arm.c in Sources */ = {isa = PBXBuildFile; fileRef = 008969072486DAD000DC48C2 /* BSG_KSMach_Arm.c */; }; @@ -431,9 +428,6 @@ 0089699F2486DAD100DC48C2 /* BSG_KSJSONCodecObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 008969192486DAD000DC48C2 /* BSG_KSJSONCodecObjC.h */; }; 008969A02486DAD100DC48C2 /* BSG_KSJSONCodecObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 008969192486DAD000DC48C2 /* BSG_KSJSONCodecObjC.h */; }; 008969A12486DAD100DC48C2 /* BSG_KSJSONCodecObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 008969192486DAD000DC48C2 /* BSG_KSJSONCodecObjC.h */; }; - 008969A22486DAD100DC48C2 /* BSG_KSDynamicLinker.h in Headers */ = {isa = PBXBuildFile; fileRef = 0089691A2486DAD000DC48C2 /* BSG_KSDynamicLinker.h */; }; - 008969A32486DAD100DC48C2 /* BSG_KSDynamicLinker.h in Headers */ = {isa = PBXBuildFile; fileRef = 0089691A2486DAD000DC48C2 /* BSG_KSDynamicLinker.h */; }; - 008969A42486DAD100DC48C2 /* BSG_KSDynamicLinker.h in Headers */ = {isa = PBXBuildFile; fileRef = 0089691A2486DAD000DC48C2 /* BSG_KSDynamicLinker.h */; }; 008969A52486DAD100DC48C2 /* BSG_KSBacktrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 0089691B2486DAD000DC48C2 /* BSG_KSBacktrace.c */; }; 008969A62486DAD100DC48C2 /* BSG_KSBacktrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 0089691B2486DAD000DC48C2 /* BSG_KSBacktrace.c */; }; 008969A72486DAD100DC48C2 /* BSG_KSBacktrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 0089691B2486DAD000DC48C2 /* BSG_KSBacktrace.c */; }; @@ -676,6 +670,13 @@ 01847DAE26441A5E00ADA4C7 /* BSGInternalErrorReporterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 01847DAB26441A5E00ADA4C7 /* BSGInternalErrorReporterTests.m */; }; 0187D464255BD7B800C503D9 /* BugsnagApiClientTest.m in Sources */ = {isa = PBXBuildFile; fileRef = CB9103632502320A00E9D1E2 /* BugsnagApiClientTest.m */; }; 019480D42625F3EB00E833ED /* BSGAppKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 019480D32625F3EB00E833ED /* BSGAppKitTests.m */; }; + 01A2C542271EB9B400A27B23 /* BSG_Symbolicate.c in Sources */ = {isa = PBXBuildFile; fileRef = 01A2C540271EB9B300A27B23 /* BSG_Symbolicate.c */; }; + 01A2C543271EB9B400A27B23 /* BSG_Symbolicate.c in Sources */ = {isa = PBXBuildFile; fileRef = 01A2C540271EB9B300A27B23 /* BSG_Symbolicate.c */; }; + 01A2C544271EB9B400A27B23 /* BSG_Symbolicate.c in Sources */ = {isa = PBXBuildFile; fileRef = 01A2C540271EB9B300A27B23 /* BSG_Symbolicate.c */; }; + 01A2C545271EB9B400A27B23 /* BSG_Symbolicate.c in Sources */ = {isa = PBXBuildFile; fileRef = 01A2C540271EB9B300A27B23 /* BSG_Symbolicate.c */; }; + 01A2C546271EB9B400A27B23 /* BSG_Symbolicate.h in Headers */ = {isa = PBXBuildFile; fileRef = 01A2C541271EB9B300A27B23 /* BSG_Symbolicate.h */; }; + 01A2C547271EB9B400A27B23 /* BSG_Symbolicate.h in Headers */ = {isa = PBXBuildFile; fileRef = 01A2C541271EB9B300A27B23 /* BSG_Symbolicate.h */; }; + 01A2C548271EB9B400A27B23 /* BSG_Symbolicate.h in Headers */ = {isa = PBXBuildFile; fileRef = 01A2C541271EB9B300A27B23 /* BSG_Symbolicate.h */; }; 01B14C56251CE55F00118748 /* report-react-native-promise-rejection.json in Resources */ = {isa = PBXBuildFile; fileRef = 01B14C55251CE55F00118748 /* report-react-native-promise-rejection.json */; }; 01B14C57251CE55F00118748 /* report-react-native-promise-rejection.json in Resources */ = {isa = PBXBuildFile; fileRef = 01B14C55251CE55F00118748 /* report-react-native-promise-rejection.json */; }; 01B14C58251CE55F00118748 /* report-react-native-promise-rejection.json in Resources */ = {isa = PBXBuildFile; fileRef = 01B14C55251CE55F00118748 /* report-react-native-promise-rejection.json */; }; @@ -881,7 +882,6 @@ E7462907248907C100F92D67 /* BSG_KSCrashSentry_CPPException.mm in Sources */ = {isa = PBXBuildFile; fileRef = 008969422486DAD000DC48C2 /* BSG_KSCrashSentry_CPPException.mm */; }; E7462908248907C100F92D67 /* BSG_KSSystemInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 0089694C2486DAD000DC48C2 /* BSG_KSSystemInfo.m */; }; E7462909248907E500F92D67 /* BSG_KSMach_x86_32.c in Sources */ = {isa = PBXBuildFile; fileRef = 008969032486DAD000DC48C2 /* BSG_KSMach_x86_32.c */; }; - E746290A248907E500F92D67 /* BSG_KSDynamicLinker.c in Sources */ = {isa = PBXBuildFile; fileRef = 008969062486DAD000DC48C2 /* BSG_KSDynamicLinker.c */; }; E746290B248907E500F92D67 /* BSG_KSMach_Arm.c in Sources */ = {isa = PBXBuildFile; fileRef = 008969072486DAD000DC48C2 /* BSG_KSMach_Arm.c */; }; E746290C248907E500F92D67 /* BSG_KSJSONCodec.c in Sources */ = {isa = PBXBuildFile; fileRef = 0089690B2486DAD000DC48C2 /* BSG_KSJSONCodec.c */; }; E746290D248907E500F92D67 /* BSG_KSMach.c in Sources */ = {isa = PBXBuildFile; fileRef = 008969132486DAD000DC48C2 /* BSG_KSMach.c */; }; @@ -945,7 +945,6 @@ E746297224890D3100F92D67 /* BSG_KSLogger.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008969152486DAD000DC48C2 /* BSG_KSLogger.h */; }; E746297324890D3100F92D67 /* BSG_KSBacktrace_Private.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008969162486DAD000DC48C2 /* BSG_KSBacktrace_Private.h */; }; E746297424890D3100F92D67 /* BSG_KSJSONCodecObjC.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008969192486DAD000DC48C2 /* BSG_KSJSONCodecObjC.h */; }; - E746297524890D3100F92D67 /* BSG_KSDynamicLinker.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0089691A2486DAD000DC48C2 /* BSG_KSDynamicLinker.h */; }; E746297724890D3100F92D67 /* BSG_KSObjCApple.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008969202486DAD000DC48C2 /* BSG_KSObjCApple.h */; }; E746297824890D3100F92D67 /* BSG_KSJSONCodec.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008969222486DAD000DC48C2 /* BSG_KSJSONCodec.h */; }; E746297924890D3100F92D67 /* BSG_KSMachHeaders.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 008969232486DAD000DC48C2 /* BSG_KSMachHeaders.h */; }; @@ -1057,7 +1056,6 @@ E746297224890D3100F92D67 /* BSG_KSLogger.h in CopyFiles */, E746297324890D3100F92D67 /* BSG_KSBacktrace_Private.h in CopyFiles */, E746297424890D3100F92D67 /* BSG_KSJSONCodecObjC.h in CopyFiles */, - E746297524890D3100F92D67 /* BSG_KSDynamicLinker.h in CopyFiles */, E746297724890D3100F92D67 /* BSG_KSObjCApple.h in CopyFiles */, E746297824890D3100F92D67 /* BSG_KSJSONCodec.h in CopyFiles */, E746297924890D3100F92D67 /* BSG_KSMachHeaders.h in CopyFiles */, @@ -1207,7 +1205,6 @@ 008969022486DAD000DC48C2 /* BSG_KSBacktrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSG_KSBacktrace.h; sourceTree = ""; }; 008969032486DAD000DC48C2 /* BSG_KSMach_x86_32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BSG_KSMach_x86_32.c; sourceTree = ""; }; 008969042486DAD000DC48C2 /* BSG_KSSysCtl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSG_KSSysCtl.h; sourceTree = ""; }; - 008969062486DAD000DC48C2 /* BSG_KSDynamicLinker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BSG_KSDynamicLinker.c; sourceTree = ""; }; 008969072486DAD000DC48C2 /* BSG_KSMach_Arm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BSG_KSMach_Arm.c; sourceTree = ""; }; 008969082486DAD000DC48C2 /* BSG_KSJSONCodecObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSG_KSJSONCodecObjC.m; sourceTree = ""; }; 008969092486DAD000DC48C2 /* BSG_KSFileUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSG_KSFileUtils.h; sourceTree = ""; }; @@ -1226,7 +1223,6 @@ 008969172486DAD000DC48C2 /* BSG_KSMach_Arm64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BSG_KSMach_Arm64.c; sourceTree = ""; }; 008969182486DAD000DC48C2 /* BSG_KSFileUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BSG_KSFileUtils.c; sourceTree = ""; }; 008969192486DAD000DC48C2 /* BSG_KSJSONCodecObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSG_KSJSONCodecObjC.h; sourceTree = ""; }; - 0089691A2486DAD000DC48C2 /* BSG_KSDynamicLinker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSG_KSDynamicLinker.h; sourceTree = ""; }; 0089691B2486DAD000DC48C2 /* BSG_KSBacktrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BSG_KSBacktrace.c; sourceTree = ""; }; 0089691C2486DAD000DC48C2 /* BSG_KSSysCtl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BSG_KSSysCtl.c; sourceTree = ""; }; 0089691E2486DAD000DC48C2 /* NSError+BSG_SimpleConstructor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+BSG_SimpleConstructor.m"; sourceTree = ""; }; @@ -1330,6 +1326,8 @@ 019480D32625F3EB00E833ED /* BSGAppKitTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BSGAppKitTests.m; sourceTree = ""; }; 0195FC3B256BC81400DE6646 /* BugsnagEvent+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BugsnagEvent+Private.h"; sourceTree = ""; }; 0198762E2567D5AB000A7AF3 /* BugsnagStackframe+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BugsnagStackframe+Private.h"; sourceTree = ""; }; + 01A2C540271EB9B300A27B23 /* BSG_Symbolicate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = BSG_Symbolicate.c; sourceTree = ""; }; + 01A2C541271EB9B300A27B23 /* BSG_Symbolicate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BSG_Symbolicate.h; sourceTree = ""; }; 01B14C55251CE55F00118748 /* report-react-native-promise-rejection.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "report-react-native-promise-rejection.json"; sourceTree = ""; }; 01B79DA7267CC4A000C8CC5E /* BSGUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BSGUtils.h; sourceTree = ""; }; 01B79DA8267CC4A000C8CC5E /* BSGUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BSGUtils.m; sourceTree = ""; }; @@ -1599,16 +1597,14 @@ 008969162486DAD000DC48C2 /* BSG_KSBacktrace_Private.h */, 0089691B2486DAD000DC48C2 /* BSG_KSBacktrace.c */, 008969022486DAD000DC48C2 /* BSG_KSBacktrace.h */, - 008969062486DAD000DC48C2 /* BSG_KSDynamicLinker.c */, - 0089691A2486DAD000DC48C2 /* BSG_KSDynamicLinker.h */, 008969182486DAD000DC48C2 /* BSG_KSFileUtils.c */, 008969092486DAD000DC48C2 /* BSG_KSFileUtils.h */, 0089690B2486DAD000DC48C2 /* BSG_KSJSONCodec.c */, 008969222486DAD000DC48C2 /* BSG_KSJSONCodec.h */, 008969192486DAD000DC48C2 /* BSG_KSJSONCodecObjC.h */, 008969082486DAD000DC48C2 /* BSG_KSJSONCodecObjC.m */, - 008969152486DAD000DC48C2 /* BSG_KSLogger.h */, 008969262486DAD000DC48C2 /* BSG_KSLogger.c */, + 008969152486DAD000DC48C2 /* BSG_KSLogger.h */, 008969072486DAD000DC48C2 /* BSG_KSMach_Arm.c */, 008969172486DAD000DC48C2 /* BSG_KSMach_Arm64.c */, 008969032486DAD000DC48C2 /* BSG_KSMach_x86_32.c */, @@ -1616,8 +1612,8 @@ 008969132486DAD000DC48C2 /* BSG_KSMach.c */, 008969282486DAD000DC48C2 /* BSG_KSMach.h */, 008969112486DAD000DC48C2 /* BSG_KSMachApple.h */, - 008969232486DAD000DC48C2 /* BSG_KSMachHeaders.h */, 008969102486DAD000DC48C2 /* BSG_KSMachHeaders.c */, + 008969232486DAD000DC48C2 /* BSG_KSMachHeaders.h */, 008969252486DAD000DC48C2 /* BSG_KSObjC.c */, 0089690F2486DAD000DC48C2 /* BSG_KSObjC.h */, 008969202486DAD000DC48C2 /* BSG_KSObjCApple.h */, @@ -1627,6 +1623,8 @@ 008969122486DAD000DC48C2 /* BSG_KSString.h */, 0089691C2486DAD000DC48C2 /* BSG_KSSysCtl.c */, 008969042486DAD000DC48C2 /* BSG_KSSysCtl.h */, + 01A2C540271EB9B300A27B23 /* BSG_Symbolicate.c */, + 01A2C541271EB9B300A27B23 /* BSG_Symbolicate.h */, 0089690C2486DAD000DC48C2 /* NSError+BSG_SimpleConstructor.h */, 0089691E2486DAD000DC48C2 /* NSError+BSG_SimpleConstructor.m */, ); @@ -2033,6 +2031,7 @@ CBAB4DD52510D2460092CBAA /* BugsnagKVStoreObjC.h in Headers */, 008968282486DA5600DC48C2 /* BugsnagKeys.h in Headers */, CBCAF6FA25A457F90095771F /* BSGFileLocations.h in Headers */, + 01A2C546271EB9B400A27B23 /* BSG_Symbolicate.h in Headers */, 008969BD2486DAD100DC48C2 /* BSG_KSMachHeaders.h in Headers */, 0126F7BB25DD512B008483C2 /* BSGEventUploadKSCrashReportOperation.h in Headers */, 008968DE2486DAA700DC48C2 /* BugsnagPluginClient.h in Headers */, @@ -2076,7 +2075,6 @@ 008969D22486DAD100DC48C2 /* BSG_KSCrashContext.h in Headers */, 008967D72486DA2D00DC48C2 /* BSGConfigurationBuilder.h in Headers */, 008969812486DAD100DC48C2 /* BSG_KSObjC.h in Headers */, - 008969A22486DAD100DC48C2 /* BSG_KSDynamicLinker.h in Headers */, CB33CCFE2703438400C76656 /* BSG_KSCrashNames.h in Headers */, 008969B42486DAD100DC48C2 /* BSG_KSObjCApple.h in Headers */, CBE9062A25A34DAB0045B965 /* BSGStorageMigratorV0V1.h in Headers */, @@ -2138,6 +2136,7 @@ CBAB4DD62510D2460092CBAA /* BugsnagKVStoreObjC.h in Headers */, 008968292486DA5600DC48C2 /* BugsnagKeys.h in Headers */, CBCAF6FB25A457F90095771F /* BSGFileLocations.h in Headers */, + 01A2C547271EB9B400A27B23 /* BSG_Symbolicate.h in Headers */, 008969BE2486DAD100DC48C2 /* BSG_KSMachHeaders.h in Headers */, 0126F7BC25DD512B008483C2 /* BSGEventUploadKSCrashReportOperation.h in Headers */, 008968DF2486DAA700DC48C2 /* BugsnagPluginClient.h in Headers */, @@ -2181,7 +2180,6 @@ 008969D32486DAD100DC48C2 /* BSG_KSCrashContext.h in Headers */, 008967D82486DA2D00DC48C2 /* BSGConfigurationBuilder.h in Headers */, 008969822486DAD100DC48C2 /* BSG_KSObjC.h in Headers */, - 008969A32486DAD100DC48C2 /* BSG_KSDynamicLinker.h in Headers */, CB33CCFF2703438400C76656 /* BSG_KSCrashNames.h in Headers */, 008969B52486DAD100DC48C2 /* BSG_KSObjCApple.h in Headers */, 008969942486DAD100DC48C2 /* BSG_KSLogger.h in Headers */, @@ -2243,6 +2241,7 @@ CBAB4DD72510D2460092CBAA /* BugsnagKVStoreObjC.h in Headers */, 0089682A2486DA5600DC48C2 /* BugsnagKeys.h in Headers */, CBCAF6FC25A457F90095771F /* BSGFileLocations.h in Headers */, + 01A2C548271EB9B400A27B23 /* BSG_Symbolicate.h in Headers */, 008969BF2486DAD100DC48C2 /* BSG_KSMachHeaders.h in Headers */, 0126F7BD25DD512B008483C2 /* BSGEventUploadKSCrashReportOperation.h in Headers */, 008968E02486DAA700DC48C2 /* BugsnagPluginClient.h in Headers */, @@ -2286,7 +2285,6 @@ 008969D42486DAD100DC48C2 /* BSG_KSCrashContext.h in Headers */, 008967D92486DA2D00DC48C2 /* BSGConfigurationBuilder.h in Headers */, 008969832486DAD100DC48C2 /* BSG_KSObjC.h in Headers */, - 008969A42486DAD100DC48C2 /* BSG_KSDynamicLinker.h in Headers */, CB33CD002703438400C76656 /* BSG_KSCrashNames.h in Headers */, 008969B62486DAD100DC48C2 /* BSG_KSObjCApple.h in Headers */, 008969952486DAD100DC48C2 /* BSG_KSLogger.h in Headers */, @@ -2616,7 +2614,6 @@ 008969A82486DAD100DC48C2 /* BSG_KSSysCtl.c in Sources */, 008969692486DAD000DC48C2 /* BSG_KSMach_Arm.c in Sources */, 008969C62486DAD100DC48C2 /* BSG_KSLogger.c in Sources */, - 008969662486DAD000DC48C2 /* BSG_KSDynamicLinker.c in Sources */, 008969C02486DAD100DC48C2 /* BSG_KSString.c in Sources */, 0126F79E25DD510E008483C2 /* BSGEventUploadObjectOperation.m in Sources */, 0089682B2486DA5600DC48C2 /* BSGSerialization.m in Sources */, @@ -2642,6 +2639,7 @@ CBE9062D25A34DAB0045B965 /* BSGStorageMigratorV0V1.m in Sources */, 010FF28725ED2A8D00E4F2B0 /* BSGAppHangDetector.m in Sources */, 00896A352486DAD100DC48C2 /* BSG_KSSystemInfo.m in Sources */, + 01A2C542271EB9B400A27B23 /* BSG_Symbolicate.c in Sources */, 01B79DAC267CC4A000C8CC5E /* BSGUtils.m in Sources */, 008969E42486DAD100DC48C2 /* BSG_KSCrashIdentifier.m in Sources */, 008967DA2486DA2D00DC48C2 /* BugsnagConfiguration.m in Sources */, @@ -2744,6 +2742,7 @@ 0089699A2486DAD100DC48C2 /* BSG_KSMach_Arm64.c in Sources */, 008967E92486DA2D00DC48C2 /* BugsnagErrorTypes.m in Sources */, 008968732486DA9500DC48C2 /* BugsnagDevice.m in Sources */, + 01A2C543271EB9B400A27B23 /* BSG_Symbolicate.c in Sources */, 0126F7AF25DD5118008483C2 /* BSGEventUploadFileOperation.m in Sources */, 008969852486DAD100DC48C2 /* BSG_KSMachHeaders.c in Sources */, 00896A332486DAD100DC48C2 /* BSG_KSCrashC.c in Sources */, @@ -2789,7 +2788,6 @@ 008969A92486DAD100DC48C2 /* BSG_KSSysCtl.c in Sources */, 0089696A2486DAD000DC48C2 /* BSG_KSMach_Arm.c in Sources */, 008969C72486DAD100DC48C2 /* BSG_KSLogger.c in Sources */, - 008969672486DAD000DC48C2 /* BSG_KSDynamicLinker.c in Sources */, 008969C12486DAD100DC48C2 /* BSG_KSString.c in Sources */, 0126F79F25DD510E008483C2 /* BSGEventUploadObjectOperation.m in Sources */, 0089682C2486DA5600DC48C2 /* BSGSerialization.m in Sources */, @@ -2960,7 +2958,6 @@ 008969AA2486DAD100DC48C2 /* BSG_KSSysCtl.c in Sources */, 0089696B2486DAD000DC48C2 /* BSG_KSMach_Arm.c in Sources */, 008969C82486DAD100DC48C2 /* BSG_KSLogger.c in Sources */, - 008969682486DAD000DC48C2 /* BSG_KSDynamicLinker.c in Sources */, 008969C22486DAD100DC48C2 /* BSG_KSString.c in Sources */, 0126F7A025DD510E008483C2 /* BSGEventUploadObjectOperation.m in Sources */, 0089682D2486DA5600DC48C2 /* BSGSerialization.m in Sources */, @@ -2986,6 +2983,7 @@ CBE9062F25A34DAB0045B965 /* BSGStorageMigratorV0V1.m in Sources */, 010FF28925ED2A8D00E4F2B0 /* BSGAppHangDetector.m in Sources */, 00896A372486DAD100DC48C2 /* BSG_KSSystemInfo.m in Sources */, + 01A2C544271EB9B400A27B23 /* BSG_Symbolicate.c in Sources */, 01B79DAE267CC4A000C8CC5E /* BSGUtils.m in Sources */, 008969E62486DAD100DC48C2 /* BSG_KSCrashIdentifier.m in Sources */, 008967DC2486DA2D00DC48C2 /* BugsnagConfiguration.m in Sources */, @@ -3084,7 +3082,6 @@ CBAA6AB8250BA01D00713376 /* BugsnagKVStore.c in Sources */, CB33CD042703438400C76656 /* BSG_KSCrashNames.c in Sources */, E7462909248907E500F92D67 /* BSG_KSMach_x86_32.c in Sources */, - E746290A248907E500F92D67 /* BSG_KSDynamicLinker.c in Sources */, E746290B248907E500F92D67 /* BSG_KSMach_Arm.c in Sources */, 0126F7B125DD5118008483C2 /* BSGEventUploadFileOperation.m in Sources */, E746290C248907E500F92D67 /* BSG_KSJSONCodec.c in Sources */, @@ -3157,6 +3154,7 @@ 00AD1F262486A17900A27979 /* Bugsnag.m in Sources */, 008968CE2486DA9600DC48C2 /* BugsnagThread.m in Sources */, 00AD1F312486A17900A27979 /* BugsnagSessionTracker.m in Sources */, + 01A2C545271EB9B400A27B23 /* BSG_Symbolicate.c in Sources */, 01B79DAF267CC4A000C8CC5E /* BSGUtils.m in Sources */, 008968C62486DA9600DC48C2 /* BugsnagUser.m in Sources */, CBB0928F2519F891007698BC /* BugsnagSystemState.m in Sources */, diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSCrashReport.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSCrashReport.c index 879b30990..1e9de6f15 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSCrashReport.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSCrashReport.c @@ -29,7 +29,6 @@ #include "BSG_KSBacktrace_Private.h" #include "BSG_KSCrashReportFields.h" #include "BSG_KSCrashReportVersion.h" -#include "BSG_KSDynamicLinker.h" #include "BSG_KSFileUtils.h" #include "BSG_KSJSONCodec.h" #include "BSG_KSMach.h" @@ -43,7 +42,9 @@ #include "BSG_KSLogger.h" #include "BSG_KSCrashContext.h" #include "BSG_KSCrashSentry.h" +#include "BSG_Symbolicate.h" +#include #include #ifdef __arm64__ @@ -530,22 +531,22 @@ void bsg_kscrw_i_logCrashType( * @param dlInfo Information about the nearest symbols to the address. */ void bsg_kscrw_i_logBacktraceEntry(const int entryNum, const uintptr_t address, - const Dl_info *const dlInfo) { + struct bsg_symbolicate_result *dlInfo) { char faddrBuff[20]; char saddrBuff[20]; - const char *fname = bsg_ksfulastPathEntry(dlInfo->dli_fname); + const char *fname = bsg_ksfulastPathEntry(dlInfo->image->name); if (fname == NULL) { - sprintf(faddrBuff, BSG_POINTER_FMT, (uintptr_t)dlInfo->dli_fbase); + sprintf(faddrBuff, BSG_POINTER_FMT, (uintptr_t)dlInfo->image->header); fname = faddrBuff; } - uintptr_t offset = address - (uintptr_t)dlInfo->dli_saddr; - const char *sname = dlInfo->dli_sname; + uintptr_t offset = address - (uintptr_t)dlInfo->function_address; + const char *sname = dlInfo->function_name; if (sname == NULL) { - sprintf(saddrBuff, BSG_POINTER_SHORT_FMT, (uintptr_t)dlInfo->dli_fbase); + sprintf(saddrBuff, BSG_POINTER_SHORT_FMT, (uintptr_t)dlInfo->image->header); sname = saddrBuff; - offset = address - (uintptr_t)dlInfo->dli_fbase; + offset = address - (uintptr_t)dlInfo->image->header; } BSG_KSLOGBASIC_ALWAYS(BSG_TRACE_FMT, entryNum, fname, address, sname, @@ -562,7 +563,7 @@ void bsg_kscrw_i_logBacktrace(const uintptr_t *const backtrace, const int backtraceLength, const int skippedEntries) { if (backtraceLength > 0) { - Dl_info symbolicated[backtraceLength]; + struct bsg_symbolicate_result symbolicated[backtraceLength]; bsg_ksbt_symbolicate(backtrace, symbolicated, backtraceLength, skippedEntries); @@ -726,23 +727,24 @@ void bsg_kscrw_i_writeAddressReferencedByString( */ void bsg_kscrw_i_writeBacktraceEntry( const BSG_KSCrashReportWriter *const writer, const char *const key, - const uintptr_t address, const Dl_info *const info) { + const uintptr_t address, struct bsg_symbolicate_result *info) { writer->beginObject(writer, key); { - if (info->dli_saddr != NULL) { - if (info->dli_fname != NULL) { - writer->addStringElement(writer, BSG_KSCrashField_ObjectName, - bsg_ksfulastPathEntry(info->dli_fname)); - } + if (info->image && info->image->header) { writer->addUIntegerElement(writer, BSG_KSCrashField_ObjectAddr, - (uintptr_t)info->dli_fbase); - if (info->dli_sname != NULL) { - const char *sname = info->dli_sname; - writer->addStringElement(writer, BSG_KSCrashField_SymbolName, - sname); - } + (uintptr_t)info->image->header); + } + if (info->image && info->image->name) { + writer->addStringElement(writer, BSG_KSCrashField_ObjectName, + bsg_ksfulastPathEntry(info->image->name)); + } + if (info->function_address) { writer->addUIntegerElement(writer, BSG_KSCrashField_SymbolAddr, - (uintptr_t)info->dli_saddr); + info->function_address); + } + if (info->function_name) { + writer->addStringElement(writer, BSG_KSCrashField_SymbolName, + info->function_name); } writer->addUIntegerElement(writer, BSG_KSCrashField_InstructionAddr, address); @@ -773,7 +775,7 @@ void bsg_kscrw_i_writeBacktrace(const BSG_KSCrashReportWriter *const writer, writer->beginArray(writer, BSG_KSCrashField_Contents); { if (backtraceLength > 0) { - Dl_info symbolicated[backtraceLength]; + struct bsg_symbolicate_result symbolicated[backtraceLength]; bsg_ksbt_symbolicate(backtrace, symbolicated, backtraceLength, skippedEntries); diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSSystemInfo.m b/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSSystemInfo.m index 48ca2bf74..1b0bf77db 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSSystemInfo.m +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/BSG_KSSystemInfo.m @@ -28,7 +28,6 @@ #import "BSG_KSSystemInfo.h" #import "BSG_KSSystemInfoC.h" -#import "BSG_KSDynamicLinker.h" #import "BSG_KSMachHeaders.h" #import "BSG_KSJSONCodecObjC.h" #import "BSG_KSMach.h" @@ -41,6 +40,8 @@ #import "BSG_KSCrash.h" #import +#import + #if BSG_PLATFORM_IOS || BSG_PLATFORM_TVOS #import "BSGUIKit.h" #endif diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSArchSpecific.h b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSArchSpecific.h index 6ed8ec1f0..7b9d3a89a 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSArchSpecific.h +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSArchSpecific.h @@ -36,12 +36,6 @@ extern "C" { #include -#ifdef __LP64__ -#define BSG_STRUCT_NLIST struct nlist_64 -#else -#define BSG_STRUCT_NLIST struct nlist -#endif - #ifdef __arm64__ #define BSG_STRUCT_MCONTEXT_L _STRUCT_MCONTEXT64 #else diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace.c index 8b0bce89f..abea3485a 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace.c @@ -26,7 +26,6 @@ #include "BSG_KSBacktrace_Private.h" -#include "BSG_KSDynamicLinker.h" #include "BSG_KSMach.h" /** @@ -225,17 +224,17 @@ int bsg_ksbt_backtraceSelf(uintptr_t *const backtraceBuffer, } void bsg_ksbt_symbolicate(const uintptr_t *const backtraceBuffer, - Dl_info *const symbolsBuffer, const int numEntries, + struct bsg_symbolicate_result *symbolsBuffer, const int numEntries, const int skippedEntries) { int i = 0; if (!skippedEntries && i < numEntries) { - bsg_ksdldladdr(backtraceBuffer[i], &symbolsBuffer[i]); + bsg_symbolicate(backtraceBuffer[i], &symbolsBuffer[i]); i++; } for (; i < numEntries; i++) { - bsg_ksdldladdr(CALL_INSTRUCTION_FROM_RETURN_ADDRESS(backtraceBuffer[i]), + bsg_symbolicate(CALL_INSTRUCTION_FROM_RETURN_ADDRESS(backtraceBuffer[i]), &symbolsBuffer[i]); } } diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace.h b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace.h index 715e76e10..e2c9790e5 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace.h +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace.h @@ -34,7 +34,8 @@ extern "C" { #endif -#include +#include "BSG_Symbolicate.h" + #include #include @@ -98,7 +99,7 @@ int bsg_ksbt_backtraceSelf(uintptr_t *backtraceBuffer, int maxEntries); * backtrace. */ void bsg_ksbt_symbolicate(const uintptr_t *backtraceBuffer, - Dl_info *symbolsBuffer, int numEntries, + struct bsg_symbolicate_result *symbolsBuffer, int numEntries, int skippedEntries); #ifdef __cplusplus diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSDynamicLinker.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSDynamicLinker.c deleted file mode 100644 index b37c81c3d..000000000 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSDynamicLinker.c +++ /dev/null @@ -1,109 +0,0 @@ -// -// KSDynamicLinker.c -// -// Created by Karl Stenerud on 2013-10-02. -// -// Copyright (c) 2012 Karl Stenerud. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall remain in place -// in this source code. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#include "BSG_KSDynamicLinker.h" -#include "BSG_KSArchSpecific.h" -#include "BSG_KSMachHeaders.h" - -#include -#include -#include - -bool bsg_ksdldladdr(const uintptr_t address, Dl_info *const info) { - info->dli_fname = NULL; - info->dli_fbase = NULL; - info->dli_sname = NULL; - info->dli_saddr = NULL; - - BSG_Mach_Header_Info *image = bsg_mach_headers_image_at_address(address); - if (image == NULL) { - return false; - } - if (address < (uintptr_t)image->slide) { - return false; - } - const uintptr_t addressWithSlide = address - (uintptr_t)image->slide; - const uintptr_t segmentBase = - bsg_mach_headers_image_at_base_of_image_index(image->header) + - (uintptr_t)image->slide; - if (segmentBase == 0) { - return false; - } - - info->dli_fname = image->name; - // Cast away constness because dli_fbase is not :'( - info->dli_fbase = (void *)(uintptr_t)image->header; - - // Find symbol tables and get whichever symbol is closest to the address. - const BSG_STRUCT_NLIST *bestMatch = NULL; - uintptr_t bestDistance = ULONG_MAX; - uintptr_t cmdPtr = bsg_mach_headers_first_cmd_after_header(image->header); - if (cmdPtr == 0) { - return false; - } - for (uint32_t iCmd = 0; iCmd < image->header->ncmds; iCmd++) { - const struct load_command *loadCmd = (struct load_command *)cmdPtr; - if (loadCmd->cmd == LC_SYMTAB) { - const struct symtab_command *symtabCmd = - (struct symtab_command *)cmdPtr; - const BSG_STRUCT_NLIST *symbolTable = - (BSG_STRUCT_NLIST *)(segmentBase + symtabCmd->symoff); - const uintptr_t stringTable = segmentBase + symtabCmd->stroff; - - for (uint32_t iSym = 0; iSym < symtabCmd->nsyms; iSym++) { - // If n_value is 0, the symbol refers to an external object. - if (symbolTable[iSym].n_value != 0) { - uintptr_t symbolBase = symbolTable[iSym].n_value; - uintptr_t currentDistance = addressWithSlide - symbolBase; - if ((addressWithSlide >= symbolBase) && - (currentDistance <= bestDistance)) { - bestMatch = symbolTable + iSym; - bestDistance = currentDistance; - } - } - } - if (bestMatch != NULL) { - info->dli_saddr = - (void *)(bestMatch->n_value + (uintptr_t)image->slide); - info->dli_sname = (char *)((intptr_t)stringTable + - (intptr_t)bestMatch->n_un.n_strx); - if (*info->dli_sname == '_') { - info->dli_sname++; - } - // This happens if all symbols have been stripped. - if (info->dli_saddr == info->dli_fbase && - bestMatch->n_type == 3) { - info->dli_sname = NULL; - } - break; - } - } - cmdPtr += loadCmd->cmdsize; - } - - return true; -} - diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSDynamicLinker.h b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSDynamicLinker.h deleted file mode 100644 index 573d66d79..000000000 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSDynamicLinker.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// KSDynamicLinker.h -// -// Created by Karl Stenerud on 2013-10-02. -// -// Copyright (c) 2012 Karl Stenerud. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall remain in place -// in this source code. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#ifndef HDR_BSG_KSDynamicLinker_h -#define HDR_BSG_KSDynamicLinker_h - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "BSG_KSMachHeaders.h" - -/** async-safe version of dladdr. - * - * This method searches the dynamic loader for information about any image - * containing the specified address. It may not be entirely successful in - * finding information, in which case any fields it could not find will be set - * to NULL. - * - * Unlike dladdr(), this method does not make use of locks, and does not call - * async-unsafe functions. - * - * @param address The address to search for. - * @param info Gets filled out by this function. - * @return true if at least some information was found. - */ -bool bsg_ksdldladdr(const uintptr_t address, Dl_info *const info); - -#ifdef __cplusplus -} -#endif - -#endif // HDR_KSDynamicLinker_h diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSMachHeaders.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSMachHeaders.c index c101508de..27c4e41fb 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSMachHeaders.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSMachHeaders.c @@ -8,7 +8,6 @@ #include "BSG_KSMachHeaders.h" -#include "BSG_KSDynamicLinker.h" #include "BSG_KSLogger.h" #include "BSG_KSMach.h" @@ -252,32 +251,6 @@ uintptr_t bsg_mach_headers_first_cmd_after_header(const struct mach_header *cons } } -uintptr_t bsg_mach_headers_image_at_base_of_image_index(const struct mach_header *const header) { - // Look for a segment command and return the file image address. - uintptr_t cmdPtr = bsg_mach_headers_first_cmd_after_header(header); - if (cmdPtr == 0) { - return 0; - } - for (uint32_t i = 0; i < header->ncmds; i++) { - const struct load_command *loadCmd = (struct load_command *)cmdPtr; - if (loadCmd->cmd == LC_SEGMENT) { - const struct segment_command *segmentCmd = - (struct segment_command *)cmdPtr; - if (strcmp(segmentCmd->segname, SEG_LINKEDIT) == 0) { - return segmentCmd->vmaddr - segmentCmd->fileoff; - } - } else if (loadCmd->cmd == LC_SEGMENT_64) { - const struct segment_command_64 *segmentCmd = - (struct segment_command_64 *)cmdPtr; - if (strcmp(segmentCmd->segname, SEG_LINKEDIT) == 0) { - return (uintptr_t)(segmentCmd->vmaddr - segmentCmd->fileoff); - } - } - cmdPtr += loadCmd->cmdsize; - } - - return 0; -} static uintptr_t bsg_mach_header_info_get_section_addr_named(const BSG_Mach_Header_Info *header, const char *name) { uintptr_t cmdPtr = bsg_mach_headers_first_cmd_after_header(header->header); if (!cmdPtr) { diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSMachHeaders.h b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSMachHeaders.h index 656466894..fd8f2732b 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSMachHeaders.h +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSMachHeaders.h @@ -113,15 +113,6 @@ BSG_Mach_Header_Info *bsg_mach_headers_image_named(const char *const imageName, */ uintptr_t bsg_mach_headers_first_cmd_after_header(const struct mach_header *header); -/** Get the segment base address of the specified image. - * - * This is required for any symtab command offsets. - * - * @param header The header to get commands for. - * @return The image's base address, or 0 if none was found. - */ -uintptr_t bsg_mach_headers_image_at_base_of_image_index(const struct mach_header *header); - /** Get the __crash_info message of the specified image. * * @param header The header to get commands for. diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c new file mode 100644 index 000000000..72acf8222 --- /dev/null +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c @@ -0,0 +1,153 @@ +// +// BSG_Symbolicate.c +// Bugsnag +// +// Copyright © 2021 Bugsnag Inc. All rights reserved. +// + +#include "BSG_Symbolicate.h" + +#include "BSG_KSLogger.h" +#include "BSG_KSMachHeaders.h" + +#include +#include +#include + +#ifdef __LP64__ +#define LC_SEGMENT_BSG LC_SEGMENT_64 +typedef struct nlist_64 nlist_t; +typedef struct segment_command_64 segment_command_t; +typedef struct section_64 section_t; +#else +#define LC_SEGMENT_BSG LC_SEGMENT +typedef struct nlist nlist_t; +typedef struct segment_command segment_command_t; +typedef struct section section_t; +#endif + +#if __clang_major__ >= 11 // Xcode 10 does not like the following attribute +__attribute__((annotate("oclint:suppress[deep nested block]"))) +#endif +bool bsg_symbolicate(const uintptr_t address, struct bsg_symbolicate_result *result) { + bzero(result, sizeof(struct bsg_symbolicate_result)); + + struct bsg_mach_image *image = bsg_mach_headers_image_at_address(address); + if (!image || !image->header) { + return false; + } + + const struct load_command *load_cmd = (const void *)bsg_mach_headers_first_cmd_after_header(image->header); + if (!load_cmd) { + return false; + } + + result->image = image; + + const uintptr_t slide = (uintptr_t)image->slide; + + const segment_command_t *linkedit = NULL; + const struct linkedit_data_command *function_starts = NULL; + const struct symtab_command *symtab = NULL; + + for (uint32_t lc_idx = 0; lc_idx < image->header->ncmds; ++lc_idx) { + switch (load_cmd->cmd) { + case LC_SEGMENT_BSG: { + const segment_command_t *seg_cmd = (const void *)load_cmd; + + // The function starts and symtab data resides in __LINKEDIT + if (strncmp(seg_cmd->segname, SEG_LINKEDIT, sizeof(seg_cmd->segname)) == 0) { + linkedit = seg_cmd; + } + + // Sanity check: the instruction address is in the __text section. + // Function Starts data only describes things within the __text section. + // We may sometimes be asked to symbolicate addresses in the __stubs section, + // which would be nice support in addition. + if (strncmp(seg_cmd->segname, SEG_TEXT, sizeof(seg_cmd->segname)) == 0) { + for (uint32_t sect_idx = 0; sect_idx < seg_cmd->nsects; sect_idx++) { + const section_t *section = (const section_t *)(seg_cmd + 1) + sect_idx; + if (strncmp(section->sectname, SECT_TEXT, sizeof(section->sectname)) == 0) { + uintptr_t start = section->addr + slide; + uintptr_t end = start + section->size; + if (address < start || address >= end) { + BSG_KSLOG_ERROR("Address %p is outside the " SECT_TEXT " section of image %s", + (void *)address, image->name); + return false; + } + break; + } + } + } + break; + } + + case LC_FUNCTION_STARTS: // first appeared in + // - cctools-800 (Xcode 4.0) + // - ld64-123.2 (Xcode 4.0) + // - dyld-195.5 (OS X 10.7 / iOS 5) + function_starts = (const void *)load_cmd; + break; + + case LC_SYMTAB: + symtab = (const void *)load_cmd; + break; + + default: + break; + } + load_cmd = (const void *)(uintptr_t)load_cmd + load_cmd->cmdsize; + } + + if (!linkedit || !function_starts) { + BSG_KSLOG_ERROR("No function start data found in %s", image->name); + return false; + } + + // The layout of segments in memory differs depending on whether the image is in the dyld cache. + // Subtracting __LINKEDIT's fileoff converts a *file* offset into an offset relative to __LINKEDIT + // that lets us compute the data's address in memory regardless of layout. +#define get_linkedit_data(__dataoff__) (const void *)(linkedit->vmaddr + slide - linkedit->fileoff + (__dataoff__)) + + // Search functions starts data for a function that contains the address + if (function_starts && function_starts->dataoff > linkedit->fileoff) { + // Function starts are stored as a series of offsets encoded as LEB128 + uintptr_t function_start = (uintptr_t)image->imageVmAddr + slide; + uintptr_t delta = 0; + uint32_t shift = 0; + const uint8_t *data = get_linkedit_data(function_starts->dataoff); + for (uint32_t i = 0; i < function_starts->datasize && data[i]; i++) { + uint8_t byte = data[i]; + delta |= ((byte & 0x7Ful) << shift); + shift += 7; + if (byte < 0x80) { // Finised decoding an integer + function_start += delta; + if (function_start >= address) { + // Previous function start was the matching one + break; + } + delta = 0; + shift = 0; + } + } + result->function_address = function_start - delta; + } + + // Find the first non-empty symbol that matches function_address + if (result->function_address && symtab && symtab->symoff > linkedit->fileoff) { + const nlist_t *symbols = get_linkedit_data(symtab->symoff); + const char *string_table = get_linkedit_data(symtab->stroff); + const uintptr_t symbol_address = (uintptr_t)result->function_address - slide; + for (uint32_t i = 0; i < symtab->nsyms; i++) { + if (symbols[i].n_value == symbol_address && + symbols[i].n_un.n_strx < symtab->strsize && + string_table[symbols[i].n_un.n_strx]) { + const char *symbol = string_table + symbols[i].n_un.n_strx; + result->function_name = symbol[0] == '_' ? symbol + 1 : symbol; + break; + } + } + } + + return true; +} diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.h b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.h new file mode 100644 index 000000000..fdf464311 --- /dev/null +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.h @@ -0,0 +1,30 @@ +// +// BSG_Symbolicate.h +// Bugsnag +// +// Copyright © 2021 Bugsnag Inc. All rights reserved. +// + +#ifndef BSG_Symbolicate_h +#define BSG_Symbolicate_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +struct bsg_symbolicate_result { + const struct bsg_mach_image *image; + uintptr_t function_address; + const char *function_name; +}; + +bool bsg_symbolicate(const uintptr_t address, struct bsg_symbolicate_result *result); + +#ifdef __cplusplus +} +#endif + +#endif // BSG_Symbolicate_h diff --git a/Bugsnag/Payload/BugsnagStackframe.m b/Bugsnag/Payload/BugsnagStackframe.m index 36e73b246..0bd4f5566 100644 --- a/Bugsnag/Payload/BugsnagStackframe.m +++ b/Bugsnag/Payload/BugsnagStackframe.m @@ -9,7 +9,8 @@ #import "BugsnagStackframe+Private.h" #import "BSG_KSBacktrace.h" -#import "BSG_KSDynamicLinker.h" +#import "BSG_KSMachHeaders.h" +#import "BSG_Symbolicate.h" #import "BugsnagCollections.h" #import "BugsnagKeys.h" #import "BugsnagLogger.h" @@ -190,22 +191,15 @@ - (void)symbolicateIfNeeded { } self.needsSymbolication = NO; - Dl_info info = {0}; - if (!dladdr((const void *)self.frameAddress.unsignedIntegerValue, &info)) { + struct bsg_symbolicate_result result; + if (!bsg_symbolicate(self.frameAddress.unsignedIntegerValue, &result)) { return; } - if (info.dli_sname) { - self.method = @(info.dli_sname); + if (result.function_address) { + self.symbolAddress = @(result.function_address); } - if (info.dli_saddr) { - self.symbolAddress = @((uintptr_t)info.dli_saddr); - } - // Just in case these were not found via bsg_mach_headers_image_at_address() - if (info.dli_fname && !self.machoFile) { - self.machoFile = @(info.dli_fname); - } - if (info.dli_fbase && self.machoLoadAddress == nil) { - self.machoLoadAddress = @((uintptr_t)info.dli_fbase); + if (result.function_name) { + self.method = @(result.function_name); } } diff --git a/Tests/BugsnagStackframeTest.m b/Tests/BugsnagStackframeTest.m index c165ba767..4a9b17e17 100644 --- a/Tests/BugsnagStackframeTest.m +++ b/Tests/BugsnagStackframeTest.m @@ -253,9 +253,19 @@ - (void)testRealCallStackSymbols { XCTAssertNotNil(stackframe.machoUuid); XCTAssertNotNil(stackframe.machoVmAddress); XCTAssertNotNil(stackframe.machoLoadAddress); + XCTAssertNil(stackframe.type); [stackframe symbolicateIfNeeded]; + if (stackframe.symbolAddress == nil && + [stackframe.machoFile isEqualToString:@"xctest"] && + [stackframe.method isEqualToString:@"main"]) { + // The final instruction of xctest's `main` function is `callq _XCTestMain` + // The return address on the stack is therefore just outside the function, and + // happens to be in the __stubs section for some versions of Xcode (e.g. 10 and 11) + // which bsg_symbolicate() correctly avoids symbolicating to "main" + NSLog(@"Skipping symbolication assertions for known bad call stack entry"); + return; + } XCTAssertNotNil(stackframe.symbolAddress); - XCTAssertNil(stackframe.type); XCTAssertTrue([callStackSymbols[idx] containsString:stackframe.method]); }]; }