…lines 1–65 unchanged (65 lines)
66 }
67 return frames
68 }
69
70 /// Given a set of stack frames, find the deepest one that should be considered
71 /// the signature of the crash.
72 private static func findInterestingSymbols(
73 _ frames: [Frame], isStackOverflow: Bool
74 ) -> [String] {
75 guard let lastFrameIdx = frames.lastIndex(
76 where: { Self.targetImageNames.contains($0.image) })
77 else {
78 return []
79 }
80 let firstFrameIdx = frames[...lastFrameIdx].reversed().firstIndex(where: {
81 !Self.targetImageNames.contains($0.image)
82 })?.base ?? frames.startIndex
83
84 let unfiltered = Array(frames[firstFrameIdx ... lastFrameIdx])
85 let filtered = unfiltered.filter { frame in
86 // Ignore frames with 0 offset, they're almost certainly bogus.
87 frame.offset != 0 && !Signature.symbols([frame.symbol], assert: nil).shouldIgnore
88 }
89 let symbols = (filtered.isEmpty ? unfiltered : filtered).map(\.symbol)
90
91 // Check for recursion
92 if isStackOverflow,
93 let recurse = symbols.reversed().findRepeatedSlice(minRepeats: 10) {
94 guard let min = recurse.min() else { return [] }
95 return [min]
96 }
97 guard let firstSymbol = symbols.first else {
98 return []
99 }
100 // Return the first full symbol, and the next symbol with a different short
101 // signature.
102 if let firstShort = Signature.symbols([firstSymbol], assert: nil).short {
103 let nextSyms = symbols.dropFirst().map {
104 Signature.symbols([$0], assert: nil)
105 }
106 let next = nextSyms.first(where: {
107 guard let nextShort = $0.short else { return false }
108 return nextShort != firstShort
109 })
110 if let next {
111 return [firstSymbol, next.short!.symbol]
112 }
113 }
114 return [firstSymbol]
115 }
116
117 private static func findAbort(_ lines: [String]) -> String? {
118 for line in lines {
119 if let match = line.wholeMatch(of: Self.abortRegex) {
120 return String(match.symbol)
…lines 121–135 unchanged (15 lines)
136 self.isStackOverflow = Self.checkStackOverflow(lines)
137 self.frames = Self.getFrames(from: lines)
138
139 let assertion = Self.findAssertion(lines)
140
141 var sig: Signature?
142
143 let syms = Self.findInterestingSymbols(frames, isStackOverflow: isStackOverflow)
144 if !syms.isEmpty {
145 sig = Signature(symbols: syms, assertion: assertion)
146 }
147 if sig == nil {
148 sig = Self.findAbort(lines)
149 .map({ Signature(symbols: [$0], assertion: assertion) })
150 }
151 if sig == nil {
152 sig = assertion.map(Signature.assertion)
153 }
154 guard let sig = sig else { return nil }
155 self.signature = sig
…lines 156–347 unchanged (192 lines)