Skip to content

Instantly share code, notes, and snippets.

@kibotu
Created June 11, 2024 10:55
Show Gist options
  • Save kibotu/bbbd761b5f4990a671964e7f8e639a58 to your computer and use it in GitHub Desktop.
Save kibotu/bbbd761b5f4990a671964e7f8e639a58 to your computer and use it in GitHub Desktop.
Thread.printStackTrace & Thread.callStack for iOS Swift. Demangled / better Thread.callStackSymbols.
import Foundation
public extension Thread {
public static var callStack : [String] {
Thread
.callStackSymbols // drop Thread.callStack
.dropFirst(
).map { line in
let parts = line.split(separator:" ")
let index = parts[0]
let module = parts[1]
let method = demangle("\(parts[3])")
return "[\(module)] \(method)"
}
}
public static func printStackTrace() {
callStack.dropFirst() // drop Thread.printStacktrace
.forEach { line in
SystemLogger.debug("[\(Thread.current.identifier)]\(line)")
}
}
}
public typealias SwiftDemangle = @convention(c) (_ mangledName: UnsafePointer<CChar>?, _ mangledNameLength: Int, _ outputBuffer: UnsafeMutablePointer<CChar>?, _ outputBufferSize: UnsafeMutablePointer<Int>?, _ flags: UInt32) -> UnsafeMutablePointer<CChar>?
public let RTLD_DEFAULT = dlopen(nil, RTLD_NOW)
public let demangleSymbol = dlsym(RTLD_DEFAULT, "swift_demangle")!
public let cDemangle = unsafeBitCast(demangleSymbol, to: SwiftDemangle.self)
public func demangle(_ mangled: String) -> String {
return mangled.withCString { cString in
// Prepare output buffer size
var size: Int = 0
let ptr = cDemangle(cString, strlen(cString), nil, &size, 0)
// Check if demangling was successful
guard let result = ptr else { return mangled }
// Convert demangled name to string
let demangledName = String(cString: result)
// Free memory allocated by swift_demangle (if necessary)
free(result)
return demangledName
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment