Skip to content

Instantly share code, notes, and snippets.

@jhaungs
Last active June 20, 2024 14:32
Show Gist options
  • Save jhaungs/26e12ea3afc4f6b9bc0c9f9af9a11709 to your computer and use it in GitHub Desktop.
Save jhaungs/26e12ea3afc4f6b9bc0c9f9af9a11709 to your computer and use it in GitHub Desktop.
Swift thread call stack trace with de-mangled names
import Foundation
enum StackTrace {
static func log(filter: String? = nil) {
let frames = Thread.callStackSymbols
.dropFirst()
.filter {filter == nil || $0.contains(filter!)}
.filter {!$0.ranges(of: /^[0-9]/).isEmpty}
guard let demangler = Demangler() else {
for frame in frames {print(frame)}
return
}
for frame in frames {
let (index, part) = parse(frame: frame)
if let name = demangler.demangle(part), filter == nil || name.contains(filter!) {
print(index, name)
}
}
}
private static func parse(frame: String) -> (String, String) {
let parts = frame.split(separator: /\s/)
let index = String(parts[0])
let part = String(parts[3])
return (index, part)
}
private struct Demangler {
private let demangle: StdlibDemangler
init?() {
guard let demangler = Self.swift_demangler else {return nil}
self.demangle = demangler
}
func demangle(_ mangled: String) -> String? {
guard let cString = demangle(mangled, mangled.utf8.count, nil, nil, 0) else {return nil}
defer {cString.deallocate()}
return String(cString: cString)
}
typealias StdlibDemangler = @convention(c) (
_ name: UnsafePointer<UInt8>?, _ length: Int,
_ buffer: UnsafeMutablePointer<UInt8>?, _ size: UnsafeMutablePointer<Int>?,
_ flags: UInt32
) -> UnsafeMutablePointer<Int8>?
private static var swift_demangler: StdlibDemangler? {
let stdlib = dlopen(nil, RTLD_NOW)
guard let symbol = dlsym(stdlib, "swift_demangle") else {return nil}
return unsafeBitCast(symbol, to: StdlibDemangler.self)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment