Skip to content

Commit

Permalink
Objc injection goto.
Browse files Browse the repository at this point in the history
  • Loading branch information
johnno1962 committed Oct 16, 2020
1 parent 4bd64cf commit d7d3d9b
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 36 deletions.
2 changes: 2 additions & 0 deletions InjectionBundle/InjectionClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#define INJECTION_ADDRESS @":8898"
#define INJECTION_KEY @"bvijkijyhbtrbrebzjbbzcfbbvvq"
#define FRAMEWORK_DELIMITER @","

@interface InjectionClient : SimpleSocket

Expand Down Expand Up @@ -50,6 +51,7 @@ typedef NS_ENUM(int, InjectionResponse) {
InjectionPause,
InjectionSign,
InjectionError,
InjectionFrameworks,

InjectionExit = ~0
};
Expand Down
24 changes: 20 additions & 4 deletions InjectionBundle/InjectionClient.mm
Original file line number Diff line number Diff line change
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#115 $
// $Id: //depot/ResidentEval/InjectionBundle/InjectionClient.mm#118 $
//

#import "InjectionClient.h"
Expand Down Expand Up @@ -163,13 +163,15 @@ + (void)load {
- (void)runInBackground {
SwiftEval *builder = [SwiftEval sharedInstance];
NSString *tmpDir = [self readString];
BOOL notPlugin = ![@"/tmp" isEqualToString:tmpDir];
builder.tmpDir = tmpDir;

if (![@"/tmp" isEqualToString:tmpDir])
if (notPlugin)
[self writeInt:INJECTION_SALT];
[self writeString:INJECTION_KEY];
[self writeString:[NSBundle
mainBundle].privateFrameworksPath];

NSString *frameworksPath = [NSBundle mainBundle].privateFrameworksPath;
[self writeString:frameworksPath];

[self writeString:builder.arch];
[self writeString:[NSBundle mainBundle].executablePath];
Expand All @@ -185,6 +187,20 @@ - (void)runInBackground {
return [reader readString].boolValue;
};

if (notPlugin) {
NSMutableArray *frameworks = [NSMutableArray new];
for (NSString *file in [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:frameworksPath error:NULL]) {
NSString *frameworkName = [file
stringByReplacingOccurrencesOfString:@".framework" withString:@""];
if (![frameworkName isEqualToString:file])
[frameworks addObject:frameworkName];
}

[self writeCommand:InjectionFrameworks withString:
[frameworks componentsJoinedByString:FRAMEWORK_DELIMITER]];
}

// As tmp file names come in, inject them
InjectionCommand command;
while ((command = (InjectionCommand)[self readInt]) != InjectionEOF) {
Expand Down
11 changes: 6 additions & 5 deletions InjectionBundle/SwiftInjection.swift
Original file line number Diff line number Diff line change
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#84 $
// $Id: //depot/ResidentEval/InjectionBundle/SwiftInjection.swift#86 $
//
// Cut-down version of code injection in Swift. Uses code
// from SwiftEval.swift to recompile and reload class.
Expand Down Expand Up @@ -341,14 +341,15 @@ public class SwiftInjection: NSObject {
}

@objc class func dumpStats() {
let top = 200
print("""
Sorted elapsed time/invocations by method
=========================================
Sorted top \(top) elapsed time/invocations by method
=================================================
""")
let invocationCounts = SwiftTrace.invocationCounts()
for (method, elapsed) in SwiftTrace.sortedElapsedTimes(onlyFirst: 1000) {
print("\(String(format: "%.1f", elapsed*1000.0))ms/\(invocationCounts[method] ?? -1)\t\(method)")
for (method, elapsed) in SwiftTrace.sortedElapsedTimes(onlyFirst: top) {
print("\(String(format: "%.1f", elapsed*1000.0))ms/\(invocationCounts[method] ?? 0)\t\(method)")
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions InjectionIII.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1215,7 +1215,6 @@
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
LD_RUNPATH_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/$(SWIFT_PLATFORM_TARGET_PREFIX) $PLATFORM_DIR/Developer/Library/Frameworks";
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_SWIFT_FLAGS = "-Xfrontend -warn-long-expression-type-checking=150";
PRODUCT_NAME = macOSInjection;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
Expand Down Expand Up @@ -1343,7 +1342,7 @@
INFOPLIST_FILE = InjectionIII/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.12;
MARKETING_VERSION = 2.3.3;
MARKETING_VERSION = 2.3.4;
PRODUCT_BUNDLE_IDENTIFIER = com.johnholdsworth.InjectionIII;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand All @@ -1366,7 +1365,7 @@
INFOPLIST_FILE = InjectionIII/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.12;
MARKETING_VERSION = 2.3.3;
MARKETING_VERSION = 2.3.4;
PRODUCT_BUNDLE_IDENTIFIER = com.johnholdsworth.InjectionIII;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down
51 changes: 31 additions & 20 deletions InjectionIII/AppDelegate.swift
Original file line number Diff line number Diff line change
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/AppDelegate.swift#71 $
// $Id: //depot/ResidentEval/InjectionIII/AppDelegate.swift#80 $
//

import Cocoa
Expand Down Expand Up @@ -235,22 +235,17 @@ class AppDelegate : NSObject, NSApplicationDelegate {
}
}

func setFrameworks(_ frameworkPath: String) {
func setFrameworks(_ frameworks: String) {
DispatchQueue.main.async {
guard let frameworksMenu = self.traceItem.submenu?
.item(withTitle: "Trace Framework")?.submenu else { return }
frameworksMenu.removeAllItems()
do {
for framework in try FileManager.default
.contentsOfDirectory(atPath: frameworkPath).sorted()
where framework.hasSuffix(".framework") {
let parts = framework.components(separatedBy: ".")
frameworksMenu.addItem(withTitle: parts[0], action:
#selector(self.traceFramework(_:)), keyEquivalent: "")
.target = self
}
} catch {
NSLog("Could not list framework driectory \(frameworkPath): \(error)")
for framework in frameworks
.components(separatedBy: FRAMEWORK_DELIMITER).sorted() {
let parts = framework.components(separatedBy: ".")
frameworksMenu.addItem(withTitle: parts[0], action:
#selector(self.traceFramework(_:)), keyEquivalent: "")
.target = self
}
}
}
Expand Down Expand Up @@ -405,27 +400,41 @@ class AppDelegate : NSObject, NSApplicationDelegate {
builder.projectFile = selectedProject

guard parts.count > 0, let (_, logsDir) =
try? builder.determineEnvironment(classNameOrFile: "") else { return }
try? builder.determineEnvironment(classNameOrFile: "") else {
lastConnection?.sendCommand(.log, with:
"💉 Injection Goto service not availble.\n")
return
}

var className: String!, sourceFile: String?
let tmpDir = NSTemporaryDirectory()

for part in parts {
className = part
let subParts = part.components(separatedBy: " ")
className = subParts[0]
if let (_, foundSourceFile) =
try? builder.findCompileCommand(logsDir: logsDir,
classNameOrFile: className, tmpfile: "/tmp/eval101") {
classNameOrFile: className, tmpfile: tmpDir+"/eval101") {
sourceFile = foundSourceFile
className = parts.last
className = subParts.count > 1 ? subParts.last : parts.last
break
}
}

className = className.replacingOccurrences(of: #"\((\S+).*"#,
with: "$1",
options: .regularExpression)

guard sourceFile != nil,
let sourceText = try? NSString(contentsOfFile: sourceFile!,
encoding: String.Encoding.utf8.rawValue),
let finder = try? NSRegularExpression(pattern:
#"\b(?:var|func|struct|class|enum)\s+(\#(className!))\b"#,
options: [.anchorsMatchLines]) else { return }
#"(?:\b(?:var|func|struct|class|enum)\s+|^[+-]\s*(?:\([^)]*\)\s*)?)(\#(className!))\b"#,
options: [.anchorsMatchLines]) else {
lastConnection?.sendCommand(.log, with:
"💉 Unable to find source file for type '\(className!)'.\n")
return
}

let match = finder.firstMatch(in: sourceText as String, options: [],
range: NSMakeRange(0, sourceText.length))
Expand All @@ -450,13 +459,15 @@ class AppDelegate : NSObject, NSApplicationDelegate {
}
}

guard numberOfLine != 0 else { return }

var xed = "/usr/bin/xed"
if let xcodeURL = self.runningXcodeDevURL {
xed = xcodeURL
.appendingPathComponent("usr/bin/xed").path
}

let script = "/tmp/injection_goto.sh"
let script = tmpDir+"/injection_goto.sh"
do {
try "\"\(xed)\" --line \(numberOfLine) \"\(sourceFile!)\""
.write(toFile: script, atomically: false, encoding: .utf8)
Expand Down
2 changes: 1 addition & 1 deletion InjectionIII/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>4401</string>
<string>4451</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
Expand Down
5 changes: 3 additions & 2 deletions InjectionIII/InjectionServer.swift
Original file line number Diff line number Diff line change
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#52 $
// $Id: //depot/ResidentEval/InjectionIII/InjectionServer.swift#53 $
//

let commandQueue = DispatchQueue(label: "InjectionCommand")
Expand Down Expand Up @@ -70,7 +70,6 @@ public class InjectionServer: SimpleSocket {
// client spcific data for building
if let frameworks = readString() {
builder.frameworks = frameworks
appDelegate.setFrameworks(frameworks)
} else { return }

if let arch = readString() {
Expand Down Expand Up @@ -182,6 +181,8 @@ public class InjectionServer: SimpleSocket {
break
}
switch command {
case .frameworks:
appDelegate.setFrameworks(readString() ?? "")
case .complete:
appDelegate.setMenuIcon("InjectionOK")
if appDelegate.frontItem.state == .on {
Expand Down

0 comments on commit d7d3d9b

Please sign in to comment.