From f05e96c65fda212964e4f223309dcd216121c497 Mon Sep 17 00:00:00 2001 From: Christoffer Winterkvist Date: Wed, 27 Mar 2019 22:15:13 +0100 Subject: [PATCH] Fix injecting Swift classes (#120) * Update expression in loadAndInject This is done to match the new format when grep-ing classes. * Refactor inject(tmpfile: String) Add new condition to match swift classes. Co-Authored-By: John Holdsworth * Bump version number to 1.5.1 * Fix log statement Co-Authored-By: John Holdsworth * Add code comment about Swift metadata Co-Authored-By: John Holdsworth * Include instructions for when to turn off code coverage. * Update README.md * Bump CFBundleVersion to 1616 --- InjectionBundle/SwiftEval.swift | 8 ++++++-- InjectionBundle/SwiftInjection.swift | 10 +++++++--- InjectionIII/Info.plist | 4 ++-- README.md | 2 +- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/InjectionBundle/SwiftEval.swift b/InjectionBundle/SwiftEval.swift index 71d6f2a8..847ff243 100644 --- a/InjectionBundle/SwiftEval.swift +++ b/InjectionBundle/SwiftEval.swift @@ -371,7 +371,11 @@ public class SwiftEval: NSObject { print("💉 Loading .dylib ...") // load patched .dylib into process with new version of class guard let dl = dlopen("\(tmpfile).dylib", RTLD_NOW) else { - throw evalError("dlopen() error: \(String(cString: dlerror()))") + let error = String(cString: dlerror()) + if error.contains("___llvm_profile_runtime") { + print("💉 Loading .dylib has failed, try turning off collection of test coverage in your scheme") + } + throw evalError("dlopen() error: \(error)") } print("💉 Loaded .dylib - Ignore any duplicate class warning ^") @@ -396,7 +400,7 @@ public class SwiftEval: NSObject { try injectGenerics(tmpfile: tmpfile, handle: dl) guard shell(command: """ - \(xcodeDev)/Toolchains/XcodeDefault.xctoolchain/usr/bin/nm \(tmpfile).o | grep -E ' S _OBJC_CLASS_\\$_| _(_T0|\\$S).*CN$' | awk '{print $3}' >\(tmpfile).classes + \(xcodeDev)/Toolchains/XcodeDefault.xctoolchain/usr/bin/nm \(tmpfile).o | grep -E ' S _OBJC_CLASS_\\$_| _(_T0|\\$S|\\$s).*CN$' | awk '{print $3}' >\(tmpfile).classes """) else { throw evalError("Could not list class symbols") } diff --git a/InjectionBundle/SwiftInjection.swift b/InjectionBundle/SwiftInjection.swift index 3ba8d387..2bccfdff 100644 --- a/InjectionBundle/SwiftInjection.swift +++ b/InjectionBundle/SwiftInjection.swift @@ -115,8 +115,12 @@ public class SwiftInjection: NSObject { let classMetadata = unsafeBitCast(newClass, to: UnsafeMutablePointer.self) // Is this a Swift class? - if (classMetadata.pointee.Data & 0x1) == 1 { - // Swift equivalent of Swizzling + // Reference: https://github.com/apple/swift/blob/master/include/swift/ABI/Metadata.h#L1195 + let oldSwiftCondition = classMetadata.pointee.Data & 0x1 == 1 + let newSwiftCondition = classMetadata.pointee.Data & 0x3 != 0 + let isSwiftClass = newSwiftCondition || oldSwiftCondition + if isSwiftClass { + // Swift equivalent of Swizzling if classMetadata.pointee.ClassSize != existingClass.pointee.ClassSize { print("💉 ⚠️ Adding or removing methods on Swift classes is not supported. Your application will likely crash. ⚠️") } @@ -129,7 +133,7 @@ public class SwiftInjection: NSObject { let vtableLength = Int(existingClass.pointee.ClassSize - existingClass.pointee.ClassAddressPoint) - vtableOffset - print("💉 Injected '\(NSStringFromClass(oldClass))'") + print("💉 Injected '\(oldClass)'") memcpy(byteAddr(existingClass) + vtableOffset, byteAddr(classMetadata) + vtableOffset, vtableLength) } diff --git a/InjectionIII/Info.plist b/InjectionIII/Info.plist index 84f6a411..dc5ff1ac 100644 --- a/InjectionIII/Info.plist +++ b/InjectionIII/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.5 + 1.5.1 CFBundleVersion - 1601 + 1616 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/README.md b/README.md index 4530f8c0..f7be1038 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ from source you'll need to use: ### Available downloads -| Xcode 9.3/4, Xcode 10 | +| Xcode 10.1, Xcode 10.2 | | ------------- | | [Mac app store](https://itunes.apple.com/app/injectioniii/id1380446739?mt=12) |