From 21285925caaae0e6aa2cb5ecd2457da5d54cc1ac Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Wed, 27 Oct 2021 16:50:25 +0100 Subject: [PATCH 1/7] Use Function Starts data for symbolication --- Bugsnag.xcodeproj/project.pbxproj | 42 ++--- .../KSCrash/Recording/BSG_KSCrashReport.c | 52 ++--- .../KSCrash/Recording/BSG_KSSystemInfo.m | 3 +- .../Recording/Tools/BSG_KSArchSpecific.h | 6 - .../KSCrash/Recording/Tools/BSG_KSBacktrace.c | 31 +-- .../KSCrash/Recording/Tools/BSG_KSBacktrace.h | 33 +++- .../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 | 177 ++++++++++++++++++ .../KSCrash/Recording/Tools/BSG_Symbolicate.h | 30 +++ Bugsnag/Payload/BugsnagStackframe.m | 24 +-- 13 files changed, 300 insertions(+), 302 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..8ae996a29 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__ @@ -525,27 +526,27 @@ void bsg_kscrw_i_logCrashType( * * @param entryNum The backtrace entry number. * - * @param address The program counter value (instruction address). + * @param address The program counter or return address value. * - * @param dlInfo Information about the nearest symbols to the address. + * @param info Information about the function that contains the address. */ void bsg_kscrw_i_logBacktraceEntry(const int entryNum, const uintptr_t address, - const Dl_info *const dlInfo) { + struct bsg_symbolicate_result *info) { char faddrBuff[20]; char saddrBuff[20]; - const char *fname = bsg_ksfulastPathEntry(dlInfo->dli_fname); + const char *fname = bsg_ksfulastPathEntry(info->image->name); if (fname == NULL) { - sprintf(faddrBuff, BSG_POINTER_FMT, (uintptr_t)dlInfo->dli_fbase); + sprintf(faddrBuff, BSG_POINTER_FMT, (uintptr_t)info->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)info->function_address; + const char *sname = info->function_name; if (sname == NULL) { - sprintf(saddrBuff, BSG_POINTER_SHORT_FMT, (uintptr_t)dlInfo->dli_fbase); + sprintf(saddrBuff, BSG_POINTER_SHORT_FMT, (uintptr_t)info->image->header); sname = saddrBuff; - offset = address - (uintptr_t)dlInfo->dli_fbase; + offset = address - (uintptr_t)info->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..4b82ff22b 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" /** @@ -38,30 +37,6 @@ #define BSG_PACStrippingMaskArm64e 0x0000000fffffffff #endif -/** Remove any pointer tagging from an instruction address - * On armv7 the least significant bit of the pointer distinguishes - * between thumb mode (2-byte instructions) and normal mode (4-byte - * instructions). On arm64 all instructions are 4-bytes wide so the two least - * significant bytes should always be 0. On x86_64 and i386, instructions are - * variable length so all bits are signficant. - */ -#if defined(__arm__) -#define DETAG_INSTRUCTION_ADDRESS(A) ((A) & ~(1UL)) -#elif defined(__arm64__) -#define DETAG_INSTRUCTION_ADDRESS(A) ((A) & ~(3UL)) -#else -#define DETAG_INSTRUCTION_ADDRESS(A) (A) -#endif - -/** Step backwards by one instruction. - * The backtrace of an objective-C program is expected to contain return - * addresses not call instructions, as that is what can easily be read from - * the stack. This is not a problem except for a few cases where the return - * address is inside a different symbol than the call address. - */ -#define CALL_INSTRUCTION_FROM_RETURN_ADDRESS(A) \ - (DETAG_INSTRUCTION_ADDRESS((A)) - 1) - /** Represents an entry in a frame list. * This is modeled after the various i386/x64 frame walkers in the xnu source, * and seems to work fine in ARM as well. I haven't included the args pointer @@ -225,17 +200,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..4b7f18a64 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace.h +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace.h @@ -34,10 +34,39 @@ extern "C" { #endif -#include +#include "BSG_Symbolicate.h" + #include #include +/** + * Remove any pointer tagging from an instruction address + * + * On armv7 the least significant bit of the pointer distinguishes + * between thumb mode (2-byte instructions) and normal mode (4-byte + * instructions). On arm64 all instructions are 4-bytes wide so the two least + * significant bytes should always be 0. On x86_64 and i386, instructions are + * variable length so all bits are signficant. + */ +#if defined(__arm__) +#define DETAG_INSTRUCTION_ADDRESS(A) ((A) & ~(1UL)) +#elif defined(__arm64__) +#define DETAG_INSTRUCTION_ADDRESS(A) ((A) & ~(3UL)) +#else +#define DETAG_INSTRUCTION_ADDRESS(A) (A) +#endif + +/** + * Step backwards by one instruction. + * + * The backtrace of an objective-C program is expected to contain return + * addresses not call instructions, as that is what can easily be read from + * the stack. This is not a problem except for a few cases where the return + * address is inside a different symbol than the call address. + */ +#define CALL_INSTRUCTION_FROM_RETURN_ADDRESS(A) \ + (DETAG_INSTRUCTION_ADDRESS((A)) - 1) + /** Generate a backtrace on the specified mach thread (async-safe). * * @@ -98,7 +127,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..72d219e7d --- /dev/null +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c @@ -0,0 +1,177 @@ +// +// 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 instruction_addr, struct bsg_symbolicate_result *result) { + bzero(result, sizeof(struct bsg_symbolicate_result)); + + struct bsg_mach_image *image = bsg_mach_headers_image_at_address(instruction_addr); + 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) { + const section_t *sections = (const section_t *)(seg_cmd + 1); + for (uint32_t sect_idx = 0; sect_idx < seg_cmd->nsects; sect_idx++) { + const section_t *section = sections + 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 (instruction_addr < start || instruction_addr >= end) { + BSG_KSLOG_ERROR("Address %p is outside the " SECT_TEXT " section of image %s", + (void *)instruction_addr, 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 LC_FUNCTION_STARTS, cannot symbolicate %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 LEB128 encoded offsets + // Starting with delta from start of __TEXT + uintptr_t addr = (uintptr_t)image->imageVmAddr + slide; + uintptr_t func_start = addr; + 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) { // Finished decoding an integer + addr += delta; + uintptr_t next_func_start = addr; +#if __arm__ + // ld64 sets the least significant bit for thumb instructions, which needs to be + // zeroed to recover the original address - see FunctionStartsAtom::encode() + // https://opensource.apple.com/source/ld64/ld64-123.2/src/ld/LinkEdit.hpp.auto.html + if (next_func_start & 1) { + next_func_start &= ~1ul; + } +#endif + if (instruction_addr < next_func_start) { + // address was in the previous function + break; + } + delta = 0; + shift = 0; + func_start = next_func_start; + } + } + result->function_address = func_start; + } + + // Find the best symbol that matches function_address. + if (result->function_address && symtab && symtab->symoff > linkedit->fileoff) { + const nlist_t *syms = get_linkedit_data(symtab->symoff); + const char *strings = get_linkedit_data(symtab->stroff); + const uintptr_t symbol_address = (uintptr_t)result->function_address - slide; + nlist_t best = {{0}}; + // Scan the whole symtab because there can be > 1 symbol with the same n_value. + // For example CoreFoundation has matching local `__forwarding_prep_0___` and + // external `_CF_forwarding_prep_0` symbols. + // Report the external symbol like dladdr, atos, lldb, et al. + for (uint32_t i = 0; i < symtab->nsyms; i++) { + if (syms[i].n_value == symbol_address && + // Sanity check string table index + syms[i].n_un.n_strx < symtab->strsize && + // Ignore empty symbol names + strings[syms[i].n_un.n_strx] && + // Prefer external symbols + ((best.n_type & N_EXT) == 0 || (syms[i].n_type & N_EXT) != 0)) { + best = syms[i]; + } + } + if (best.n_value) { + const char *name = strings + best.n_un.n_strx; + result->function_name = name[0] == '_' ? name + 1 : name; + } + } + + 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..6a0bbb902 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,17 @@ - (void)symbolicateIfNeeded { } self.needsSymbolication = NO; - Dl_info info = {0}; - if (!dladdr((const void *)self.frameAddress.unsignedIntegerValue, &info)) { + uintptr_t frameAddress = self.frameAddress.unsignedIntegerValue; + uintptr_t instructionAddress = self.isPc ? frameAddress: CALL_INSTRUCTION_FROM_RETURN_ADDRESS(frameAddress); + struct bsg_symbolicate_result result; + if (!bsg_symbolicate(instructionAddress, &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); } } From 78b5c7ada720b73ca7c009660c839a0925eea615 Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 28 Oct 2021 13:57:44 +0100 Subject: [PATCH 2/7] Use bzero(result, sizeof(*result)) --- .../KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c index 72d219e7d..18c91fd42 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c @@ -30,7 +30,7 @@ typedef struct section section_t; __attribute__((annotate("oclint:suppress[deep nested block]"))) #endif bool bsg_symbolicate(const uintptr_t instruction_addr, struct bsg_symbolicate_result *result) { - bzero(result, sizeof(struct bsg_symbolicate_result)); + bzero(result, sizeof(*result)); struct bsg_mach_image *image = bsg_mach_headers_image_at_address(instruction_addr); if (!image || !image->header) { From 80ab55737cd135d151765d794b99c5ff2eabcb18 Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 28 Oct 2021 13:58:19 +0100 Subject: [PATCH 3/7] Remove redundant function_starts check --- .../Source/KSCrash/Recording/Tools/BSG_Symbolicate.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c index 18c91fd42..9c9ee1e52 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c @@ -100,18 +100,13 @@ bool bsg_symbolicate(const uintptr_t instruction_addr, struct bsg_symbolicate_re load_cmd = (const void *)(uintptr_t)load_cmd + load_cmd->cmdsize; } - if (!linkedit || !function_starts) { - BSG_KSLOG_ERROR("No LC_FUNCTION_STARTS, cannot symbolicate %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) { + if (function_starts && linkedit && function_starts->dataoff > linkedit->fileoff) { // Function starts are stored as a series of LEB128 encoded offsets // Starting with delta from start of __TEXT uintptr_t addr = (uintptr_t)image->imageVmAddr + slide; @@ -144,6 +139,9 @@ bool bsg_symbolicate(const uintptr_t instruction_addr, struct bsg_symbolicate_re } } result->function_address = func_start; + } else { + BSG_KSLOG_ERROR("No LC_FUNCTION_STARTS, cannot symbolicate %s", image->name); + return; } // Find the best symbol that matches function_address. From 41ca36adc0ee0503ffc9db20ed2beab435d6881e Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 28 Oct 2021 13:58:33 +0100 Subject: [PATCH 4/7] #define THUMB_INSTRUCTION_TAG --- .../KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c index 9c9ee1e52..32e0315ca 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c @@ -122,11 +122,12 @@ bool bsg_symbolicate(const uintptr_t instruction_addr, struct bsg_symbolicate_re addr += delta; uintptr_t next_func_start = addr; #if __arm__ +#define THUMB_INSTRUCTION_TAG 1ul // ld64 sets the least significant bit for thumb instructions, which needs to be // zeroed to recover the original address - see FunctionStartsAtom::encode() // https://opensource.apple.com/source/ld64/ld64-123.2/src/ld/LinkEdit.hpp.auto.html - if (next_func_start & 1) { - next_func_start &= ~1ul; + if (next_func_start & THUMB_INSTRUCTION_TAG) { + next_func_start &= ~THUMB_INSTRUCTION_TAG; } #endif if (instruction_addr < next_func_start) { From dee75b72cd2cad59454fe490e4108f133e52bb25 Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 28 Oct 2021 13:59:20 +0100 Subject: [PATCH 5/7] Make bsg_symbolicate void --- .../KSCrash/Recording/Tools/BSG_KSBacktrace_Private.h | 1 + .../Source/KSCrash/Recording/Tools/BSG_Symbolicate.c | 10 ++++------ .../Source/KSCrash/Recording/Tools/BSG_Symbolicate.h | 3 +-- Bugsnag/Payload/BugsnagStackframe.m | 5 ++--- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace_Private.h b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace_Private.h index 4e7eae369..5f83ae3e3 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace_Private.h +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_KSBacktrace_Private.h @@ -34,6 +34,7 @@ extern "C" { #include "BSG_KSArchSpecific.h" #include "BSG_KSBacktrace.h" +#include #include /** Point at which bsg_ksbt_backtraceLength() will give up trying to count. diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c index 32e0315ca..e197aed68 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c @@ -29,17 +29,17 @@ typedef struct section section_t; #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 instruction_addr, struct bsg_symbolicate_result *result) { +void bsg_symbolicate(const uintptr_t instruction_addr, struct bsg_symbolicate_result *result) { bzero(result, sizeof(*result)); struct bsg_mach_image *image = bsg_mach_headers_image_at_address(instruction_addr); if (!image || !image->header) { - return false; + return; } const struct load_command *load_cmd = (const void *)bsg_mach_headers_first_cmd_after_header(image->header); if (!load_cmd) { - return false; + return; } result->image = image; @@ -74,7 +74,7 @@ bool bsg_symbolicate(const uintptr_t instruction_addr, struct bsg_symbolicate_re if (instruction_addr < start || instruction_addr >= end) { BSG_KSLOG_ERROR("Address %p is outside the " SECT_TEXT " section of image %s", (void *)instruction_addr, image->name); - return false; + return; } break; } @@ -171,6 +171,4 @@ bool bsg_symbolicate(const uintptr_t instruction_addr, struct bsg_symbolicate_re result->function_name = name[0] == '_' ? name + 1 : name; } } - - return true; } diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.h b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.h index fdf464311..e4de0f97a 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.h +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.h @@ -12,7 +12,6 @@ extern "C" { #endif -#include #include struct bsg_symbolicate_result { @@ -21,7 +20,7 @@ struct bsg_symbolicate_result { const char *function_name; }; -bool bsg_symbolicate(const uintptr_t address, struct bsg_symbolicate_result *result); +void bsg_symbolicate(const uintptr_t address, struct bsg_symbolicate_result *result); #ifdef __cplusplus } diff --git a/Bugsnag/Payload/BugsnagStackframe.m b/Bugsnag/Payload/BugsnagStackframe.m index 6a0bbb902..e31734627 100644 --- a/Bugsnag/Payload/BugsnagStackframe.m +++ b/Bugsnag/Payload/BugsnagStackframe.m @@ -194,9 +194,8 @@ - (void)symbolicateIfNeeded { uintptr_t frameAddress = self.frameAddress.unsignedIntegerValue; uintptr_t instructionAddress = self.isPc ? frameAddress: CALL_INSTRUCTION_FROM_RETURN_ADDRESS(frameAddress); struct bsg_symbolicate_result result; - if (!bsg_symbolicate(instructionAddress, &result)) { - return; - } + bsg_symbolicate(instructionAddress, &result); + if (result.function_address) { self.symbolAddress = @(result.function_address); } From d80f46b3207066f0a29ed302a41fa418a65dbd29 Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 28 Oct 2021 14:14:44 +0100 Subject: [PATCH 6/7] Extract LEB128 decoder --- .../KSCrash/Recording/Tools/BSG_Symbolicate.c | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c index e197aed68..6bf7ca6b3 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c @@ -26,6 +26,23 @@ typedef struct segment_command segment_command_t; typedef struct section section_t; #endif +struct leb128_uintptr_context { + uintptr_t value; + uint32_t shift; +}; + +static int leb128_uintptr_decode(struct leb128_uintptr_context *context, uint8_t input, uintptr_t *output) { + context->value |= ((input & 0x7Ful) << context->shift); + context->shift += 7; + if (input < 0x80) { + *output = context->value; + context->value = 0; + context->shift = 0; + return 1; + } + return 0; +} + #if __clang_major__ >= 11 // Xcode 10 does not like the following attribute __attribute__((annotate("oclint:suppress[deep nested block]"))) #endif @@ -107,18 +124,15 @@ void bsg_symbolicate(const uintptr_t instruction_addr, struct bsg_symbolicate_re // Search functions starts data for a function that contains the address if (function_starts && linkedit && function_starts->dataoff > linkedit->fileoff) { - // Function starts are stored as a series of LEB128 encoded offsets + // Function starts are stored as a series of LEB128 encoded deltas // Starting with delta from start of __TEXT uintptr_t addr = (uintptr_t)image->imageVmAddr + slide; uintptr_t func_start = addr; - uintptr_t delta = 0; - uint32_t shift = 0; + struct leb128_uintptr_context context = {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) { // Finished decoding an integer + uintptr_t delta; + if (leb128_uintptr_decode(&context, data[i], &delta)) { addr += delta; uintptr_t next_func_start = addr; #if __arm__ @@ -134,8 +148,6 @@ void bsg_symbolicate(const uintptr_t instruction_addr, struct bsg_symbolicate_re // address was in the previous function break; } - delta = 0; - shift = 0; func_start = next_func_start; } } From 669f10005f3f5bf8e7a3497d4f29b8ac3273c32c Mon Sep 17 00:00:00 2001 From: Nick Dowell Date: Thu, 28 Oct 2021 16:18:48 +0100 Subject: [PATCH 7/7] Fix potential early exit of function starts parsing --- .../Source/KSCrash/Recording/Tools/BSG_Symbolicate.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c index 6bf7ca6b3..a6e7719c9 100644 --- a/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c +++ b/Bugsnag/KSCrash/Source/KSCrash/Recording/Tools/BSG_Symbolicate.c @@ -31,10 +31,11 @@ struct leb128_uintptr_context { uint32_t shift; }; +// Process a single byte of LEB128-encoded data and return 1 if it was the last byte of a value. static int leb128_uintptr_decode(struct leb128_uintptr_context *context, uint8_t input, uintptr_t *output) { context->value |= ((input & 0x7Ful) << context->shift); context->shift += 7; - if (input < 0x80) { + if (input < 0x80) { // The most significant bit is not set, so this is the last byte. *output = context->value; context->value = 0; context->shift = 0; @@ -130,9 +131,9 @@ void bsg_symbolicate(const uintptr_t instruction_addr, struct bsg_symbolicate_re uintptr_t func_start = addr; struct leb128_uintptr_context context = {0}; const uint8_t *data = get_linkedit_data(function_starts->dataoff); - for (uint32_t i = 0; i < function_starts->datasize && data[i]; i++) { - uintptr_t delta; - if (leb128_uintptr_decode(&context, data[i], &delta)) { + for (uint32_t i = 0; i < function_starts->datasize; i++) { + uintptr_t delta = 0; + if (leb128_uintptr_decode(&context, data[i], &delta) && delta) { addr += delta; uintptr_t next_func_start = addr; #if __arm__