Skip to content

Commit

Permalink
feat: add structured class for stackframe
Browse files Browse the repository at this point in the history
  • Loading branch information
fractalwrench committed Apr 7, 2020
1 parent 5b2be57 commit 413e92b
Show file tree
Hide file tree
Showing 11 changed files with 404 additions and 93 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ Bugsnag Notifiers on other platforms.

## Enhancements

* Create structured `BugsnagStackframe` class
[#528](https://github.com/bugsnag/bugsnag-cocoa/pull/528)

* Convert `event.app` from `NSDictionary` to a structured class
[#520](https://github.com/bugsnag/bugsnag-cocoa/pull/520)

Expand Down
38 changes: 27 additions & 11 deletions OSX/Bugsnag.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
8A87352C1C6D3B1600EDBD5B /* BSG_KSCrashReportWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A87352B1C6D3B1600EDBD5B /* BSG_KSCrashReportWriter.h */; settings = {ATTRIBUTES = (Public, ); }; };
8AD1E3FA23EDDD4F0044F919 /* BSGConnectivityTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8AD1E3F823EDDD3F0044F919 /* BSGConnectivityTest.m */; };
8AD9FA891E086351002859A7 /* BugsnagConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8AD9FA851E0862DC002859A7 /* BugsnagConfigurationTests.m */; };
E722105E243B6A0F0083CF15 /* BugsnagStackframeTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E722105D243B6A0E0083CF15 /* BugsnagStackframeTest.m */; };
E72352C11F55924A00436528 /* BSGConnectivity.h in Headers */ = {isa = PBXBuildFile; fileRef = E72352BF1F55924A00436528 /* BSGConnectivity.h */; };
E72352C21F55924A00436528 /* BSGConnectivity.m in Sources */ = {isa = PBXBuildFile; fileRef = E72352C01F55924A00436528 /* BSGConnectivity.m */; };
E72AE1F9241A4E7500ED8972 /* BugsnagPluginClient.m in Sources */ = {isa = PBXBuildFile; fileRef = E72AE1F7241A4E7500ED8972 /* BugsnagPluginClient.m */; };
Expand Down Expand Up @@ -200,6 +201,9 @@
E7CE78D01FD94E77001D07E0 /* RFC3339DateTool_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7CE78981FD94E60001D07E0 /* RFC3339DateTool_Tests.m */; };
E7CE78D51FD94E93001D07E0 /* XCTestCase+KSCrash.m in Sources */ = {isa = PBXBuildFile; fileRef = E7CE788A1FD94E5F001D07E0 /* XCTestCase+KSCrash.m */; };
E7CE78D61FD94E9E001D07E0 /* FileBasedTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = E7CE788B1FD94E5F001D07E0 /* FileBasedTestCase.m */; };
E7D2E673243B8FA8005A3041 /* BugsnagStacktrace.h in Headers */ = {isa = PBXBuildFile; fileRef = E7D2E671243B8FA7005A3041 /* BugsnagStacktrace.h */; };
E7D2E674243B8FA8005A3041 /* BugsnagStacktrace.m in Sources */ = {isa = PBXBuildFile; fileRef = E7D2E672243B8FA7005A3041 /* BugsnagStacktrace.m */; };
E7D2E676243B8FB6005A3041 /* BugsnagStacktraceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E7D2E675243B8FB6005A3041 /* BugsnagStacktraceTest.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -267,6 +271,7 @@
8A87352B1C6D3B1600EDBD5B /* BSG_KSCrashReportWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BSG_KSCrashReportWriter.h; path = ../Source/BSG_KSCrashReportWriter.h; sourceTree = SOURCE_ROOT; };
8AD1E3F823EDDD3F0044F919 /* BSGConnectivityTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BSGConnectivityTest.m; sourceTree = "<group>"; };
8AD9FA851E0862DC002859A7 /* BugsnagConfigurationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BugsnagConfigurationTests.m; path = ../Tests/BugsnagConfigurationTests.m; sourceTree = SOURCE_ROOT; };
E722105D243B6A0E0083CF15 /* BugsnagStackframeTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagStackframeTest.m; sourceTree = "<group>"; };
E72352BF1F55924A00436528 /* BSGConnectivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BSGConnectivity.h; path = ../Source/BSGConnectivity.h; sourceTree = SOURCE_ROOT; };
E72352C01F55924A00436528 /* BSGConnectivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BSGConnectivity.m; path = ../Source/BSGConnectivity.m; sourceTree = SOURCE_ROOT; };
E72AE1F7241A4E7500ED8972 /* BugsnagPluginClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BugsnagPluginClient.m; path = ../Source/BugsnagPluginClient.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -418,6 +423,9 @@
E7CE789E1FD94E60001D07E0 /* KSLogger_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSLogger_Tests.m; sourceTree = "<group>"; };
E7CE789F1FD94E60001D07E0 /* XCTestCase+KSCrash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCTestCase+KSCrash.h"; sourceTree = "<group>"; };
E7CE78A01FD94E60001D07E0 /* KSCrashState_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSCrashState_Tests.m; sourceTree = "<group>"; };
E7D2E671243B8FA7005A3041 /* BugsnagStacktrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BugsnagStacktrace.h; path = ../Source/BugsnagStacktrace.h; sourceTree = "<group>"; };
E7D2E672243B8FA7005A3041 /* BugsnagStacktrace.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BugsnagStacktrace.m; path = ../Source/BugsnagStacktrace.m; sourceTree = "<group>"; };
E7D2E675243B8FB6005A3041 /* BugsnagStacktraceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BugsnagStacktraceTest.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -502,6 +510,8 @@
8A48EF261EAA805D00B70024 /* BugsnagLogger.h */,
E79148391FD82B34003EFEBF /* BugsnagSessionTracker.h */,
E79148431FD82B36003EFEBF /* BugsnagSessionTracker.m */,
E7D2E671243B8FA7005A3041 /* BugsnagStacktrace.h */,
E7D2E672243B8FA7005A3041 /* BugsnagStacktrace.m */,
8A2C8FA61C6BC1F700846019 /* Info.plist */,
8A2C902F1C6BF3AC00846019 /* module.modulemap */,
E79E6B081F4E3850002B35F9 /* BSG_KSCrash */,
Expand All @@ -513,26 +523,28 @@
8A2C8FAF1C6BC1F700846019 /* Tests */ = {
isa = PBXGroup;
children = (
8AD1E3F823EDDD3F0044F919 /* BSGConnectivityTest.m */,
E790C4A22434CB6A006FFB26 /* BugsnagAppTest.m */,
E790C41F2432314A006FFB26 /* BugsnagClientMirrorTest.m */,
E7AB4B9D2423E184004F015A /* BugsnagOnBreadcrumbTest.m */,
00F9393B23FD2D9B008C7073 /* BugsnagTestsDummyClass.h */,
00F9393A23FD2D9B008C7073 /* BugsnagTestsDummyClass.m */,
00F9393123FC168F008C7073 /* BugsnagBaseUnitTest.h */,
00F9393223FC168F008C7073 /* BugsnagBaseUnitTest.m */,
00D7ACA223E984B300FBE4A7 /* BugsnagEventTests.m */,
8AD1E3F823EDDD3F0044F919 /* BSGConnectivityTest.m */,
8A2C8FE01C6BC38200846019 /* BugsnagBreadcrumbsTest.m */,
E790C41F2432314A006FFB26 /* BugsnagClientMirrorTest.m */,
4B406C1622CAD96400464D1D /* BugsnagCollectionsBSGDictMergeTest.m */,
4B406C1722CAD96400464D1D /* BugsnagCollectionsBSGDictSetSafeObjectTest.m */,
4B775FD222CBE02A004839C5 /* BugsnagCollectionsBSGDictInsertIfNotNilTest.m */,
8AD9FA851E0862DC002859A7 /* BugsnagConfigurationTests.m */,
00D7ACA223E984B300FBE4A7 /* BugsnagEventTests.m */,
E762E9F71F73F7E900E82B43 /* BugsnagHandledStateTest.m */,
E7AB4B9D2423E184004F015A /* BugsnagOnBreadcrumbTest.m */,
E791482D1FD82B0C003EFEBF /* BugsnagSessionTest.m */,
E791482B1FD82B0C003EFEBF /* BugsnagSessionTrackerTest.m */,
E791482C1FD82B0C003EFEBF /* BugsnagSessionTrackingPayloadTest.m */,
E791482E1FD82B0C003EFEBF /* BugsnagUserTest.m */,
E762E9F71F73F7E900E82B43 /* BugsnagHandledStateTest.m */,
8AD9FA851E0862DC002859A7 /* BugsnagConfigurationTests.m */,
8A2C8FE01C6BC38200846019 /* BugsnagBreadcrumbsTest.m */,
8A2C8FE21C6BC38200846019 /* BugsnagSinkTests.m */,
E7D2E675243B8FB6005A3041 /* BugsnagStacktraceTest.m */,
E722105D243B6A0E0083CF15 /* BugsnagStackframeTest.m */,
E791482E1FD82B0C003EFEBF /* BugsnagUserTest.m */,
00F9393B23FD2D9B008C7073 /* BugsnagTestsDummyClass.h */,
00F9393A23FD2D9B008C7073 /* BugsnagTestsDummyClass.m */,
8A2C8FE41C6BC38200846019 /* report.json */,
8A2C8FB21C6BC1F700846019 /* TestsInfo.plist */,
E7CE78861FD94E40001D07E0 /* KSCrash */,
Expand Down Expand Up @@ -758,8 +770,8 @@
children = (
E790C46524349CE1006FFB26 /* BugsnagApp.h */,
E790C46924349CE2006FFB26 /* BugsnagApp.m */,
E790C46D24349CE2006FFB26 /* BugsnagAppWithState.m */,
E790C46724349CE2006FFB26 /* BugsnagAppWithState.h */,
E790C46D24349CE2006FFB26 /* BugsnagAppWithState.m */,
E790C46A24349CE2006FFB26 /* BugsnagDevice.h */,
E790C46B24349CE2006FFB26 /* BugsnagDevice.m */,
E790C46624349CE1006FFB26 /* BugsnagDeviceWithState.h */,
Expand Down Expand Up @@ -893,6 +905,7 @@
E79E6B911F4E3850002B35F9 /* BSG_KSCrashReport.h in Headers */,
8A48EF271EAA805D00B70024 /* BugsnagLogger.h in Headers */,
E79E6BCC1F4E3850002B35F9 /* BSG_KSSingleton.h in Headers */,
E7D2E673243B8FA8005A3041 /* BugsnagStacktrace.h in Headers */,
8A2C8FCD1C6BC2C800846019 /* Bugsnag.h in Headers */,
8A2C8FCF1C6BC2C800846019 /* BugsnagBreadcrumb.h in Headers */,
E79148511FD82B36003EFEBF /* BugsnagApiClient.h in Headers */,
Expand Down Expand Up @@ -1070,6 +1083,7 @@
E79E6BAF1F4E3850002B35F9 /* BSG_KSBacktrace.c in Sources */,
E79E6B941F4E3850002B35F9 /* BSG_KSCrashReportStore.m in Sources */,
E790C47724349CE2006FFB26 /* BugsnagApp.m in Sources */,
E7D2E674243B8FA8005A3041 /* BugsnagStacktrace.m in Sources */,
E79E6B9D1F4E3850002B35F9 /* BSG_KSSystemInfo.m in Sources */,
E79E6B051F4E3847002B35F9 /* BugsnagErrorReportApiClient.m in Sources */,
E79148571FD82B36003EFEBF /* BugsnagSession.m in Sources */,
Expand Down Expand Up @@ -1103,6 +1117,7 @@
E7CE78C91FD94E77001D07E0 /* KSSignalInfo_Tests.m in Sources */,
E7CE78C61FD94E77001D07E0 /* KSMach_Tests.m in Sources */,
00F9393C23FD2D9B008C7073 /* BugsnagTestsDummyClass.m in Sources */,
E7D2E676243B8FB6005A3041 /* BugsnagStacktraceTest.m in Sources */,
E7CE78D61FD94E9E001D07E0 /* FileBasedTestCase.m in Sources */,
E7CE78D51FD94E93001D07E0 /* XCTestCase+KSCrash.m in Sources */,
E7CE78CF1FD94E77001D07E0 /* NSError+SimpleConstructor_Tests.m in Sources */,
Expand All @@ -1126,6 +1141,7 @@
00F9393323FC168F008C7073 /* BugsnagBaseUnitTest.m in Sources */,
E7CE78BE1FD94E77001D07E0 /* KSCrashSentry_NSException_Tests.m in Sources */,
E7CE78C21FD94E77001D07E0 /* KSDynamicLinker_Tests.m in Sources */,
E722105E243B6A0F0083CF15 /* BugsnagStackframeTest.m in Sources */,
E7CE78CA1FD94E77001D07E0 /* KSString_Tests.m in Sources */,
E762E9F91F73F7F300E82B43 /* BugsnagHandledStateTest.m in Sources */,
E7CE78C51FD94E77001D07E0 /* KSLogger_Tests.m in Sources */,
Expand Down
71 changes: 12 additions & 59 deletions Source/BugsnagEvent.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#import "BSG_RFC3339DateTool.h"
#import "BugsnagKeys.h"
#import "BugsnagClient.h"
#import "BugsnagStacktrace.h"

static NSString *const DEFAULT_EXCEPTION_TYPE = @"cocoa";

Expand Down Expand Up @@ -71,53 +72,12 @@ - (NSDictionary *)toDictionary;
- (id)deepCopy;
@end

// MARK: - KSCrashReport parsing

NSMutableDictionary *BSGFormatFrame(NSDictionary *frame,
NSArray *binaryImages) {
NSMutableDictionary *formatted = [NSMutableDictionary dictionary];

unsigned long instructionAddress =
[frame[@"instruction_addr"] unsignedLongValue];
unsigned long symbolAddress = [frame[@"symbol_addr"] unsignedLongValue];
unsigned long imageAddress = [frame[@"object_addr"] unsignedLongValue];

BSGDictSetSafeObject(
formatted, [NSString stringWithFormat:BSGKeyFrameAddrFormat, instructionAddress],
@"frameAddress");
BSGDictSetSafeObject(formatted,
[NSString stringWithFormat:BSGKeyFrameAddrFormat, symbolAddress],
BSGKeySymbolAddr);
BSGDictSetSafeObject(formatted,
[NSString stringWithFormat:BSGKeyFrameAddrFormat, imageAddress],
BSGKeyMachoLoadAddr);
BSGDictInsertIfNotNil(formatted, frame[BSGKeyIsPC], BSGKeyIsPC);
BSGDictInsertIfNotNil(formatted, frame[BSGKeyIsLR], BSGKeyIsLR);

NSString *file = frame[@"object_name"];
NSString *method = frame[@"symbol_name"];

BSGDictInsertIfNotNil(formatted, file, BSGKeyMachoFile);
BSGDictInsertIfNotNil(formatted, method, @"method");

for (NSDictionary *image in binaryImages) {
if ([(NSNumber *)image[@"image_addr"] unsignedLongValue] ==
imageAddress) {
unsigned long imageSlide =
[image[@"image_vmaddr"] unsignedLongValue];

BSGDictInsertIfNotNil(formatted, image[@"uuid"], BSGKeyMachoUUID);
BSGDictInsertIfNotNil(formatted, image[BSGKeyName], BSGKeyMachoFile);
BSGDictSetSafeObject(
formatted, [NSString stringWithFormat:BSGKeyFrameAddrFormat, imageSlide],
BSGKeyMachoVMAddress);

return formatted;
}
}
@interface BugsnagStackframe ()
+ (BugsnagStackframe *)frameFromDict:(NSDictionary *)dict
withImages:(NSArray *)binaryImages;
@end

return nil;
}
// MARK: - KSCrashReport parsing

NSString *_Nonnull BSGParseErrorClass(NSDictionary *error,
NSString *errorType) {
Expand Down Expand Up @@ -576,7 +536,7 @@ - (NSDictionary *)toJson {
if (self.customException) {
BSGDictSetSafeObject(event, @[ self.customException ], BSGKeyExceptions);
BSGDictSetSafeObject(event, [self serializeThreadsWithException:nil],
BSGKeyThreads);
BSGKeyThreads);
} else {
NSMutableDictionary *exception = [NSMutableDictionary dictionary];
BSGDictSetSafeObject(exception, [self errorClass], BSGKeyErrorClass);
Expand Down Expand Up @@ -676,12 +636,11 @@ - (NSArray *)serializeThreadsWithException:(NSMutableDictionary *)exception {
containsObject:[self errorType]]) {
BSGDictSetSafeObject(mutableFrame, @YES, BSGKeyIsLR);
}
BSGArrayInsertIfNotNil(
stacktrace,
BSGFormatFrame(mutableFrame, [self binaryImages]));
BSGArrayInsertIfNotNil(stacktrace, mutableFrame);
}
}
BSGDictSetSafeObject(exception, stacktrace, BSGKeyStacktrace);
BugsnagStacktrace *trace = [[BugsnagStacktrace alloc] initWithTrace:stacktrace binaryImages:self.binaryImages];
BSGDictSetSafeObject(exception, [trace toArray], BSGKeyStacktrace);
}
[self serialiseThread:bugsnagThreads thread:thread backtrace:backtrace reportingThread:isReportingThread];
}
Expand All @@ -692,16 +651,10 @@ - (void)serialiseThread:(NSMutableArray *)bugsnagThreads
thread:(NSDictionary *)thread
backtrace:(NSArray *)backtrace
reportingThread:(BOOL)isReportingThread {
NSMutableArray *threadStack = [NSMutableArray array];

for (NSDictionary *frame in backtrace) {
BSGArrayInsertIfNotNil(
threadStack, BSGFormatFrame(frame, [self binaryImages]));
}

BugsnagStacktrace *stacktrace = [[BugsnagStacktrace alloc] initWithTrace:backtrace binaryImages:self.binaryImages];
NSMutableDictionary *threadDict = [NSMutableDictionary dictionary];
BSGDictSetSafeObject(threadDict, thread[@"index"], BSGKeyId);
BSGDictSetSafeObject(threadDict, threadStack, BSGKeyStacktrace);
BSGDictSetSafeObject(threadDict, [stacktrace toArray], BSGKeyStacktrace);
BSGDictSetSafeObject(threadDict, DEFAULT_EXCEPTION_TYPE, BSGKeyType);

if (isReportingThread) {
Expand Down
49 changes: 45 additions & 4 deletions Source/BugsnagStackframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,54 @@

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

/**
* Represents a single stackframe from a stacktrace.
*/
@interface BugsnagStackframe : NSObject

@end
/**
* The method name of the stackframe
*/
@property(nullable) NSString *method;

NS_ASSUME_NONNULL_END
/**
* The Mach-O file used by the stackframe
*/
@property(nullable) NSString *machoFile;

/**
* A UUID identifying the Mach-O file used by the stackframe
*/
@property(nullable) NSString *machoUuid;

/**
* The stack frame address
*/
@property unsigned long frameAddress;

/**
* The VM address of the Mach-O file
*/
@property unsigned long machoVmAddress;

/**
* The address of the stackframe symbol
*/
@property unsigned long symbolAddress;

/**
* The load address of the Mach-O file
*/
@property unsigned long machoLoadAddress;

/**
* Whether the frame was within the program counter
*/
@property BOOL isPc;

/**
* Whether the frame was within the link register
*/
@property BOOL isLr;

@end
53 changes: 53 additions & 0 deletions Source/BugsnagStackframe.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,60 @@
//

#import "BugsnagStackframe.h"
#import "BugsnagKeys.h"
#import "BugsnagCollections.h"

@implementation BugsnagStackframe

+ (NSDictionary *_Nullable)findImageAddr:(unsigned long)addr inImages:(NSArray *)images {
for (NSDictionary *image in images) {
if ([(NSNumber *)image[@"image_addr"] unsignedLongValue] == addr) {
return image;
}
}
return nil;
}

+ (BugsnagStackframe *)frameFromDict:(NSDictionary *)dict
withImages:(NSArray *)binaryImages {
BugsnagStackframe *frame = [BugsnagStackframe new];
frame.frameAddress = [dict[@"instruction_addr"] unsignedLongValue];
frame.symbolAddress = [dict[@"symbol_addr"] unsignedLongValue];
frame.machoLoadAddress = [dict[@"object_addr"] unsignedLongValue];
frame.machoFile = dict[@"object_name"];
frame.method = dict[@"symbol_name"];
frame.isPc = [dict[BSGKeyIsPC] boolValue];
frame.isLr = [dict[BSGKeyIsLR] boolValue];

NSDictionary *image = [self findImageAddr:frame.machoLoadAddress inImages:binaryImages];

if (image != nil) {
frame.machoUuid = image[@"uuid"];
frame.machoVmAddress = [image[@"image_vmaddr"] unsignedLongValue];
return frame;
} else { // invalid frame, skip
return nil;
}
}

- (NSDictionary *)toDict {
NSMutableDictionary *dict = [NSMutableDictionary new];
BSGDictInsertIfNotNil(dict, self.machoFile, BSGKeyMachoFile);
BSGDictInsertIfNotNil(dict, self.method, @"method");
BSGDictInsertIfNotNil(dict, self.machoUuid, BSGKeyMachoUUID);

NSString *frameAddr = [NSString stringWithFormat:BSGKeyFrameAddrFormat, self.frameAddress];
BSGDictSetSafeObject(dict, frameAddr, @"frameAddress");

NSString *symbolAddr = [NSString stringWithFormat:BSGKeyFrameAddrFormat, self.symbolAddress];
BSGDictSetSafeObject(dict, symbolAddr, BSGKeySymbolAddr);

NSString *imageAddr = [NSString stringWithFormat:BSGKeyFrameAddrFormat, self.machoLoadAddress];
BSGDictSetSafeObject(dict, imageAddr, BSGKeyMachoLoadAddr);

NSString *vmAddr = [NSString stringWithFormat:BSGKeyFrameAddrFormat, self.machoVmAddress];
BSGDictSetSafeObject(dict, vmAddr, BSGKeyMachoVMAddress);
return dict;
}

@end
25 changes: 25 additions & 0 deletions Source/BugsnagStacktrace.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// BugsnagStacktrace.h
// Bugsnag
//
// Created by Jamie Lynch on 06/04/2020.
// Copyright © 2020 Bugsnag. All rights reserved.
//

#import <Foundation/Foundation.h>

@class BugsnagStackframe;

/**
* Representation of a stacktrace in a bugsnag error report
*/
@interface BugsnagStacktrace : NSObject

- (instancetype)initWithTrace:(NSArray<NSDictionary *> *)trace
binaryImages:(NSArray<NSDictionary *> *)binaryImages;

- (NSArray *)toArray;

@property NSMutableArray<BugsnagStackframe *> *trace;

@end
Loading

0 comments on commit 413e92b

Please sign in to comment.