Skip to content

Commit

Permalink
Afterthoughts.
Browse files Browse the repository at this point in the history
  • Loading branch information
johnno1962 committed Oct 23, 2020
1 parent 66b317f commit b81b7fd
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 81 deletions.
1 change: 0 additions & 1 deletion InjectionBundle/InjectionClient.h
Expand Up @@ -58,7 +58,6 @@ typedef NS_ENUM(int, InjectionResponse) {
InjectionError,
InjectionFrameworkList,
InjectionCallOrderList,
InjectionCallReorderList,

InjectionExit = ~0
};
Expand Down
13 changes: 7 additions & 6 deletions InjectionBundle/InjectionClient.mm
Expand Up @@ -5,7 +5,7 @@
// Created by John Holdsworth on 06/11/2017.
// Copyright © 2017 John Holdsworth. All rights reserved.
//
// $Id: //depot/ResidentEval/InjectionBundle/InjectionClient.mm#133 $
// $Id: //depot/ResidentEval/InjectionBundle/InjectionClient.mm#135 $
//

#import "InjectionClient.h"
Expand Down Expand Up @@ -301,7 +301,10 @@ - (void)runInBackground {
[self filteringChanged];
break;
case InjectionStats:
[SwiftInjection dumpStats];
static int top = 200;
printf("\n💉 Sorted top %d elapsed time/invocations by method\n"
"💉 =================================================\n", top);
[SwiftInjection dumpStatsWithTop:top];
[self needsTracing];
break;
case InjectionCallOrder:
Expand All @@ -315,13 +318,11 @@ - (void)runInBackground {
printf("\n💉 Source files in the order they were first referenced:\n"
"💉 =====================================================\n"
"💉 (Order the source files should be compiled in target)\n");
[self writeCommand:InjectionCallOrderList
withString:[[SwiftInjection callOrder]
componentsJoinedByString:CALLORDER_DELIMITER]];
[SwiftInjection fileOrder];
[self needsTracing];
break;
case InjectionFileReorder:
[self writeCommand:InjectionCallReorderList
[self writeCommand:InjectionCallOrderList
withString:[[SwiftInjection callOrder]
componentsJoinedByString:CALLORDER_DELIMITER]];
[self needsTracing];
Expand Down
21 changes: 18 additions & 3 deletions InjectionBundle/SwiftEval.swift
Expand Up @@ -5,7 +5,7 @@
// Created by John Holdsworth on 02/11/2017.
// Copyright © 2017 John Holdsworth. All rights reserved.
//
// $Id: //depot/ResidentEval/InjectionBundle/SwiftEval.swift#146 $
// $Id: //depot/ResidentEval/InjectionBundle/SwiftEval.swift#149 $
//
// Basic implementation of a Swift "eval()" including the
// mechanics of recompiling a class and loading the new
Expand Down Expand Up @@ -724,6 +724,21 @@ public class SwiftEval: NSObject {
.first
}

class func uniqueTypeNames(signatures: [String], exec: (String) -> Void) {
var typesSearched = Set<String>()

for signature in signatures {
let parts = signature.components(separatedBy: ".")
if parts.count < 3 {
continue
}
let typeName = parts[1]
if typesSearched.insert(typeName).inserted {
exec(typeName)
}
}
}

func shell(command: String) -> Bool {
let commandFile = "\(tmpDir)/command.sh"
try! command.write(toFile: commandFile, atomically: false, encoding: .utf8)
Expand All @@ -732,7 +747,7 @@ public class SwiftEval: NSObject {
#if os(macOS)
let task = Process()
task.launchPath = "/bin/bash"
task.arguments = ["-c", command]
task.arguments = [commandFile]
task.launch()
task.waitUntilExit()
return task.terminationStatus == EXIT_SUCCESS
Expand All @@ -758,7 +773,7 @@ public class SwiftEval: NSObject {
if fork() == 0 {
let commandsIn = fdopen(commandsPipe[ForReading], "r")
let statusesOut = fdopen(statusesPipe[ForWriting], "w")
var buffer = [Int8](repeating: 0, count: 4096)
var buffer = [Int8](repeating: 0, count: Int(MAXPATHLEN))

close(commandsPipe[ForWriting])
close(statusesPipe[ForReading])
Expand Down
41 changes: 30 additions & 11 deletions InjectionBundle/SwiftInjection.swift
Expand Up @@ -5,7 +5,7 @@
// Created by John Holdsworth on 05/11/2017.
// Copyright © 2017 John Holdsworth. All rights reserved.
//
// $Id: //depot/ResidentEval/InjectionBundle/SwiftInjection.swift#89 $
// $Id: //depot/ResidentEval/InjectionBundle/SwiftInjection.swift#91 $
//
// Cut-down version of code injection in Swift. Uses code
// from SwiftEval.swift to recompile and reload class.
Expand Down Expand Up @@ -214,7 +214,8 @@ public class SwiftInjection: NSObject {
(loadedFunc, symbol, _, _) in
guard let existing = dlsym(main, symbol) else { return }
// has this symbol already been interposed?
let current = SwiftTrace.interposed[existing] ?? existing
let current = SwiftTrace.interposed[existing] ??
UnsafeRawPointer(existing)
let tuple = dyld_interpose_tuple(
replacement: loadedFunc, replacee: current)
interposes.append(tuple)
Expand All @@ -226,8 +227,7 @@ public class SwiftInjection: NSObject {
}

// Using array of new interpose structs
interposes.withUnsafeBufferPointer {
interps in
interposes.withUnsafeBufferPointer { interps in

var mostRecentlyLoaded = true
// Apply interposes to all images in the app bundle
Expand Down Expand Up @@ -347,13 +347,7 @@ public class SwiftInjection: NSObject {
}
}

@objc class func dumpStats() {
let top = 200
print("""
💉 Sorted top \(top) elapsed time/invocations by method
💉 =================================================
""")
@objc class func dumpStats(top: Int) {
let invocationCounts = SwiftTrace.invocationCounts()
for (method, elapsed) in SwiftTrace.sortedElapsedTimes(onlyFirst: top) {
print("\(String(format: "%.1f", elapsed*1000.0))ms/\(invocationCounts[method] ?? 0)\t\(method)")
Expand All @@ -363,6 +357,31 @@ public class SwiftInjection: NSObject {
@objc class func callOrder() -> [String] {
return SwiftTrace.callOrder().map { $0.signature }
}

@objc class func fileOrder() {
let builder = SwiftEval.sharedInstance()
let signatures = callOrder()

guard let projectRoot = builder.projectFile.flatMap({
URL(fileURLWithPath: $0).deletingLastPathComponent().path+"/"
}),
let (_, logsDir) =
try? builder.determineEnvironment(classNameOrFile: "") else {
print("💉 File ordering not available.")
return
}

let tmpfile = builder.tmpDir+"/eval101"

SwiftEval.uniqueTypeNames(signatures: signatures) { typeName in
if !typeName.contains("("), let (_, foundSourceFile) =
try? builder.findCompileCommand(logsDir: logsDir,
classNameOrFile: typeName, tmpfile: tmpfile) {
print(foundSourceFile
.replacingOccurrences(of: projectRoot, with: ""))
}
}
}
}

class SwiftSweeper {
Expand Down
8 changes: 6 additions & 2 deletions InjectionIII.xcodeproj/project.pbxproj
Expand Up @@ -83,6 +83,7 @@
BBE64E5D2524D1B50049B6D4 /* SwiftEval.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB439B8A1FABA65D00B4F50B /* SwiftEval.swift */; };
BBEB704C1FD28C6F00127711 /* XcodeHash.m in Sources */ = {isa = PBXBuildFile; fileRef = BBEB704B1FD28C6F00127711 /* XcodeHash.m */; };
BD35949E21A6C5DE0020EB94 /* Vaccine.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD35949D21A6C5DE0020EB94 /* Vaccine.swift */; };
CEBE11CD25418CF900B468FE /* SwiftTrace-Swift.h in Headers */ = {isa = PBXBuildFile; fileRef = CEBE11CC25418CF900B468FE /* SwiftTrace-Swift.h */; };
CEC1702A253ED117002E823F /* Experimental.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC17029253ED117002E823F /* Experimental.swift */; };
CEC17035253ED472002E823F /* SwiftRegex in Frameworks */ = {isa = PBXBuildFile; productRef = CEC17034253ED472002E823F /* SwiftRegex */; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -263,6 +264,7 @@
BBEB704B1FD28C6F00127711 /* XcodeHash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XcodeHash.m; sourceTree = "<group>"; };
BD35949D21A6C5DE0020EB94 /* Vaccine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vaccine.swift; sourceTree = "<group>"; };
BDB6A7CE21824C800001CF95 /* UserDefaults.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UserDefaults.h; sourceTree = "<group>"; };
CEBE11CC25418CF900B468FE /* SwiftTrace-Swift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SwiftTrace-Swift.h"; path = "SwiftTraceGuts/SwiftTrace-Swift.h"; sourceTree = "<group>"; };
CEC17029253ED117002E823F /* Experimental.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Experimental.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -441,6 +443,7 @@
children = (
BB6C87F72520D2C3005AFCFC /* xt_forwarding_trampoline_arm64.s */,
BB6C87F82520D2C3005AFCFC /* xt_forwarding_trampoline_x64.s */,
CEBE11CC25418CF900B468FE /* SwiftTrace-Swift.h */,
BB6C87C62520D0D2005AFCFC /* SwiftTrace.h */,
BB6C87F62520D2C3005AFCFC /* SwiftTrace.mm */,
BB6C87EA2520D152005AFCFC /* SwiftTrace.swift */,
Expand Down Expand Up @@ -585,6 +588,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
CEBE11CD25418CF900B468FE /* SwiftTrace-Swift.h in Headers */,
BB6C87D62520D0D2005AFCFC /* SwiftTrace.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -1385,7 +1389,7 @@
INFOPLIST_FILE = InjectionIII/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.12;
MARKETING_VERSION = 2.3.5;
MARKETING_VERSION = 2.4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.johnholdsworth.InjectionIII;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand All @@ -1408,7 +1412,7 @@
INFOPLIST_FILE = InjectionIII/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.12;
MARKETING_VERSION = 2.3.5;
MARKETING_VERSION = 2.4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.johnholdsworth.InjectionIII;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 3 additions & 46 deletions InjectionIII/Experimental.swift
Expand Up @@ -5,7 +5,7 @@
// Created by User on 20/10/2020.
// Copyright © 2020 John Holdsworth. All rights reserved.
//
// $Id: //depot/ResidentEval/InjectionIII/Experimental.swift#21 $
// $Id: //depot/ResidentEval/InjectionIII/Experimental.swift#22 $
//

import Cocoa
Expand Down Expand Up @@ -40,33 +40,6 @@ extension AppDelegate {
lastConnection?.sendCommand(.fileReorder, with: nil)
}

func fileOrder(signatures: [String]) {
let builder = SwiftEval()
builder.projectFile = selectedProject

guard let projectRoot = selectedProject.flatMap({
URL(fileURLWithPath: $0).deletingLastPathComponent().path+"/"
}),
let (_, logsDir) =
try? builder.determineEnvironment(classNameOrFile: "") else {
lastConnection?.sendCommand(.log, with:
"💉 File ordering not available.")
return
}

let tmpfile = NSTemporaryDirectory()+"/eval101"

uniqueTypeNames(signatures: signatures) { typeName in
if let (_, foundSourceFile) =
try? builder.findCompileCommand(logsDir: logsDir,
classNameOrFile: typeName, tmpfile: tmpfile) {
let relativePath = foundSourceFile
.replacingOccurrences(of: projectRoot, with: "")
lastConnection?.sendCommand(.log, with: relativePath)
}
}
}

func fileReorder(signatures: [String]) {
var projectEncoding: String.Encoding = .utf8
let projectURL = selectedProject.flatMap {
Expand All @@ -85,7 +58,7 @@ extension AppDelegate {

var orders = ["AppDelegate.swift": 0]
var order = 1
uniqueTypeNames(signatures: signatures) { typeName in
SwiftEval.uniqueTypeNames(signatures: signatures) { typeName in
orders[typeName+".swift"] = order
order += 1
}
Expand Down Expand Up @@ -136,27 +109,11 @@ extension AppDelegate {
}
}

func uniqueTypeNames(signatures: [String], exec: (String) -> Void) {
var typesSearched = Set<String>()

for signature in signatures {
let parts = signature.components(separatedBy: ".")
if parts.count < 3 {
continue
}
let typeName = parts[1]
if typesSearched.insert(typeName).inserted {
exec(typeName)
}
}
}


/// Entry point for "Injection Goto" service
/// - Parameters:
/// - pboard: NSPasteboard containing selected type [+method) name
/// - userData: N/A
/// - error: N/A
/// - errorPtr: NSString describing error on error
@objc func injectionGoto(_ pboard: NSPasteboard, userData: NSString,
error errorPtr: UnsafeMutablePointer<NSString>) {
guard pboard.canReadObject(forClasses: [NSString.self], options:nil),
Expand Down
2 changes: 1 addition & 1 deletion InjectionIII/Info.plist
Expand Up @@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>4681</string>
<string>4767</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
Expand Down
10 changes: 2 additions & 8 deletions InjectionIII/InjectionServer.swift
Expand Up @@ -5,7 +5,7 @@
// Created by John Holdsworth on 06/11/2017.
// Copyright © 2017 John Holdsworth. All rights reserved.
//
// $Id: //depot/ResidentEval/InjectionIII/InjectionServer.swift#57 $
// $Id: //depot/ResidentEval/InjectionIII/InjectionServer.swift#58 $
//

let commandQueue = DispatchQueue(label: "InjectionCommand")
Expand Down Expand Up @@ -220,15 +220,9 @@ public class InjectionServer: SimpleSocket {
sendCommand(.signed, with: signedOK ? "1": "0")
break
case .callOrderList:
fallthrough
case .callReorderList:
if let calls = readString()?
.components(separatedBy: CALLORDER_DELIMITER) {
if command == .callOrderList {
appDelegate.fileOrder(signatures: calls)
} else {
appDelegate.fileReorder(signatures: calls)
}
appDelegate.fileReorder(signatures: calls)
}
break
case .error:
Expand Down
6 changes: 5 additions & 1 deletion InjectionIII/build_bundles.sh
Expand Up @@ -6,7 +6,7 @@
# Created by John Holdsworth on 04/10/2019.
# Copyright © 2019 John Holdsworth. All rights reserved.
#
# $Id: //depot/ResidentEval/InjectionIII/build_bundles.sh#43 $
# $Id: //depot/ResidentEval/InjectionIII/build_bundles.sh#44 $
#

# Injection has to assume a fixed path for Xcode.app as it uses
Expand All @@ -29,6 +29,10 @@ function build_bundle () {
"$DEVELOPER_BIN_DIR"/xcodebuild SYMROOT=$SYMROOT ARCHS="$ARCHS" -sdk $SDK -config $CONFIGURATION -target SwiftUISupport
}

if [ -w "$SRCROOT/SwiftTrace/SwiftTraceGuts/SwiftTrace-Swift.h" ]; then
rsync -au "$BUILT_PRODUCTS_DIR/SwiftTrace.framework/Versions/A/Headers/SwiftTrace-Swift.h" "$SRCROOT/SwiftTrace/SwiftTraceGuts"
fi &&

#build_bundle macOS MacOSX macosx &&
build_bundle iOS iPhoneSimulator iphonesimulator &&
build_bundle tvOS AppleTVSimulator appletvsimulator &&
Expand Down

0 comments on commit b81b7fd

Please sign in to comment.