Hello everyone,
After a very successful serverside conference last week, and a bunch of discussions with various members of the community, I came up with a few small improvements that I’d like to pitch.
First of which is the long overdue exposing a simple demangle function. This was first discussed in 2019 (!), and followed up on in 2024 however neither attempts went all the way through evolution; so here’s another attempt at it.
You can view the complete pitch here: SE-NNNN: Expose demangle function in Runtime module. (Pull request)
Expose demangle function in Runtime module
- Proposal: SE-NNNN
- Authors: Konrad'ktoso'Malawski, Alejandro Alonso
- Review Manager: TODO
- Status: TODO
- Implementation: PR #84788
- Review:
- Previous pitch
Introduction
Swift symbols are subject to name mangling. These mangled names then show up in backtraces and other profiling tools. Mangled names may look something like this $sSS7cStringSSSPys4Int8VG_tcfC and often end up visible to developers, unless they are demangled before displaying.
In manu situations, it is much preferable to demangle the identifiers before displaying them. For example, the previously shown identifier would can be demangled as Swift.String.init(cString: Swift.UnsafePointer<Swift.Int8>) -> Swift.String, which is a nice human-readable format, that a Swift developer can easily understand.
This proposal introduces a new API that allows calling out to the Swift runtime's demangler, without leaving the process.
Motivation
Currently, many tools that need to display symbol names to developers are forced to create a process and execute the swift-demangle tool, or use unofficial runtime APIs to invoke the runtime's demangler.
Neither of these approaches are satisfactionary, because either we are paying a high cost for creating processes, or we're relying on unofficial APIs.
This proposal introduces an official demangle(:String) -> String? function that offers a maintained and safe way to call the Swift demangled from a running Swift application.
Proposed solution
We propose to introduce two demangle functions in the Runtime module:
A simple demangle method, returning an optional String:
public func demangle(_ mangledName: String) -> String?
And an overload which accepts a pre-allocated buffer into which the demangled string can be written:
@discardableResult
public func demangle(
_ mangledName: String,
into buffer: UnsafeMutableBufferPointer<Int8>
) -> DemanglingResult
public enum DemanglingResult: Equatable {
case success
case failed
case truncated(Int)
}
The buffer accepting API is necessary for performance sensitive use-cases, which attempt to demangle symbols in process, before displaying or sending them for further processing. In those use-cases it is common to have a known maximum buffer size into which we are willing to write the demangled representation.
If the demangled representation does not fit the preallocated buffer, the demangle method will return truncated(actualSize) such that developers can determine by how much the buffer might need to be increased to handle the complete demangling.
Demangling format
While the mangled strings are part of Swift ABI and can therefore not really change on platforms with stable ABI, the demangled representation returned by the demangle functions is not guaranteed to be stable in any way.
The demangled representation may change without any warning, during even patch releases of Swift. The returned strings should be treated mostly as nicer to present to developers human readable representations, and it is not a goal to provide any form of guarantee about the exact shape of these.