From a3a87559a17d48bc4869114b61614076561bf62b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20S=C3=B8rb=C3=B8?= Date: Thu, 29 Aug 2024 18:40:31 +0200 Subject: [PATCH 1/2] demangle swift --- index.js | 30 ++++++++++++++++++++---------- lib/api.js | 16 +++++++++++++++- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index ce73ffb..2f0083c 100644 --- a/index.js +++ b/index.js @@ -270,7 +270,8 @@ function Runtime() { numClasses = api.objc_getClassList(classHandles, numClasses); for (let i = 0; i !== numClasses; i++) { const handle = classHandles.add(i * pointerSize).readPointer(); - const name = api.class_getName(handle).readUtf8String(); + const rawName = api.class_getName(handle) + const name = tryDemangleSwift(rawName) ?? rawName.readUtf8String(); cachedClasses[name] = handle; } numCachedClasses = numClasses; @@ -544,12 +545,14 @@ function Runtime() { return cachedClass; case "$className": if (cachedClassName === null) { + let rawName = null; if (superSpecifier) - cachedClassName = api.class_getName(superSpecifier.add(pointerSize).readPointer()).readUtf8String(); + rawName = api.class_getName(superSpecifier.add(pointerSize).readPointer()); else if (isClass()) - cachedClassName = api.class_getName(handle).readUtf8String(); + rawName = api.class_getName(handle); else - cachedClassName = api.object_getClassName(handle).readUtf8String(); + rawName = api.object_getClassName(handle); + cachedClassName = tryDemangleSwift(rawName) ?? rawName.readUtf8String();; } return cachedClassName; case "$moduleName": @@ -1691,29 +1694,36 @@ function Runtime() { const classHandle = classHandles.add(i * pointerSize).readPointer(); const rawName = classGetName(classHandle); - let name = null; + let name = tryDemangleSwift(rawName); let modulePath = modules.findPath(rawName); const possiblySwift = (modulePath === null) && (unfiltered || allModules.findPath(rawName) === null); if (possiblySwift) { - name = rawName.readCString(); - const probablySwift = name.indexOf('.') !== -1; + const swiftName = rawName.readCString(); + const probablySwift = swiftName.indexOf('.') !== -1; if (probablySwift) { const nominalTypeDescriptor = classHandle.add(swiftNominalTypeDescriptorOffset).readPointer(); modulePath = modules.findPath(nominalTypeDescriptor); + name ??= swiftName; } } if (modulePath !== null) { - if (name === null) - name = rawName.readUtf8String(); - onMatch(name, modulePath); + onMatch(name ?? rawName.readUtf8String(), modulePath); } } callbacks.onComplete(); } + function tryDemangleSwift (symbol) { + if (api.swift_demangle === undefined) return null; + const demangled = api.swift_demangle(symbol, api._platform_strlen(symbol), ptr(0), 0, 0); + const demangledString = demangled !== null ? demangled.readUtf8String() : null; + if (demangled !== null) api.free(demangled) + return demangledString; + } + function enumerateLoadedClassesSync(options = {}) { const result = {}; enumerateLoadedClasses(options, { diff --git a/lib/api.js b/lib/api.js index 4697491..10f626a 100644 --- a/lib/api.js +++ b/lib/api.js @@ -14,7 +14,13 @@ function getApi() { { module: "libsystem_malloc.dylib", functions: { - "free": ['void', ['pointer']] + "free": ['void', ['pointer']], + } + }, + { + module: "libsystem_c.dylib", + functions: { + "_platform_strlen": ['size_t', ['pointer']] } }, { module: "libobjc.A.dylib", @@ -96,6 +102,14 @@ function getApi() { this._dispatch_main_q = address; } } + }, { + module: "libswiftCore.dylib", + functions: { + "swift_demangle": ['pointer', ['pointer', 'size_t', 'pointer', 'size_t', 'uint32']] + }, + optionals: { + "swift_demangle": 'ABI' + } } ]; let remaining = 0; From 5ef6cf861dec55dac5ff97f76a30219eb7a51829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5vard=20S=C3=B8rb=C3=B8?= Date: Thu, 5 Sep 2024 12:53:20 +0200 Subject: [PATCH 2/2] Use old style nullish coalescing --- index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 2f0083c..70c2878 100644 --- a/index.js +++ b/index.js @@ -271,7 +271,7 @@ function Runtime() { for (let i = 0; i !== numClasses; i++) { const handle = classHandles.add(i * pointerSize).readPointer(); const rawName = api.class_getName(handle) - const name = tryDemangleSwift(rawName) ?? rawName.readUtf8String(); + const name = tryDemangleSwift(rawName) || rawName.readUtf8String(); cachedClasses[name] = handle; } numCachedClasses = numClasses; @@ -552,7 +552,7 @@ function Runtime() { rawName = api.class_getName(handle); else rawName = api.object_getClassName(handle); - cachedClassName = tryDemangleSwift(rawName) ?? rawName.readUtf8String();; + cachedClassName = tryDemangleSwift(rawName) || rawName.readUtf8String();; } return cachedClassName; case "$moduleName": @@ -1704,12 +1704,12 @@ function Runtime() { if (probablySwift) { const nominalTypeDescriptor = classHandle.add(swiftNominalTypeDescriptorOffset).readPointer(); modulePath = modules.findPath(nominalTypeDescriptor); - name ??= swiftName; + name = name || swiftName; } } if (modulePath !== null) { - onMatch(name ?? rawName.readUtf8String(), modulePath); + onMatch(name || rawName.readUtf8String(), modulePath); } }