1
+ import ArgumentParser
1
2
import SwiftRemoteMirror
2
3
3
4
@@ -12,47 +13,6 @@ func machErrStr(_ kr: kern_return_t) -> String {
12
13
return " \( errStr) (0x \( errHex) ) "
13
14
}
14
15
15
-
16
- var argv = ArraySlice ( CommandLine . arguments)
17
- guard let executableName = argv. popFirst ( ) else {
18
- argFail ( " Command line arguments are completely empty! " )
19
- }
20
-
21
- struct Command {
22
- var name : String
23
- var help : String
24
- var call : ( inout ArraySlice < String > ) throws -> Void
25
-
26
- init ( name: String , help: String ,
27
- call: @escaping ( inout ArraySlice < String > ) -> Void ) {
28
- self . name = name
29
- self . help = help
30
- self . call = call
31
- }
32
-
33
- init ( name: String , help: String ,
34
- call: @escaping ( SwiftReflectionContextRef ) throws -> Void ) {
35
- self . name = name
36
- self . help = help
37
- self . call = { try withReflectionContext ( args: & $0, call: call) }
38
- }
39
- }
40
-
41
- let commands = [
42
- Command (
43
- name: " dump-conformance-cache " ,
44
- help: " Print the contents of the target's protocol conformance cache. " ,
45
- call: dumpConformanceCache) ,
46
- Command (
47
- name: " dump-metadata-allocations " ,
48
- help: " Print the target's metadata allocations. " ,
49
- call: dumpMetadataAllocations) ,
50
- Command (
51
- name: " help " ,
52
- help: " Print this help. " ,
53
- call: printUsage) ,
54
- ]
55
-
56
16
func dumpConformanceCache( context: SwiftReflectionContextRef ) throws {
57
17
try context. iterateConformanceCache ( call: { type, proto in
58
18
let typeName = context. name ( metadata: type) ?? " <unknown> "
@@ -90,29 +50,10 @@ func dumpMetadataAllocations(context: SwiftReflectionContextRef) throws {
90
50
}
91
51
}
92
52
93
- func printUsage( args: inout ArraySlice < String > ) {
94
- print ( " Usage: \( executableName) <command> " , to: & Std. err)
95
- print ( " " , to: & Std. err)
96
- print ( " Available commands: " , to: & Std. err)
97
-
98
- let maxWidth = commands. map ( { $0. name. count } ) . max ( ) ?? 0
99
- for command in commands {
100
- var paddedName = command. name
101
- while paddedName. count < maxWidth {
102
- paddedName = " " + paddedName
103
- }
104
- print ( " \( paddedName) - \( command. help) " , to: & Std. err)
105
- }
106
- }
107
-
108
- func makeReflectionContext( args: inout ArraySlice < String > )
53
+ func makeReflectionContext( nameOrPid: String )
109
54
-> ( Inspector , SwiftReflectionContextRef ) {
110
- guard let pidStr = args. popFirst ( ) else {
111
- argFail ( " Must specify a pid or process name " )
112
- }
113
-
114
- guard let pid = pidFromHint ( pidStr) else {
115
- argFail ( " Cannot find pid/process \( pidStr) " )
55
+ guard let pid = pidFromHint ( nameOrPid) else {
56
+ argFail ( " Cannot find pid/process \( nameOrPid) " )
116
57
}
117
58
118
59
guard let inspector = Inspector ( pid: pid) else {
@@ -133,36 +74,51 @@ func makeReflectionContext(args: inout ArraySlice<String>)
133
74
}
134
75
135
76
func withReflectionContext(
136
- args : inout ArraySlice < String > ,
77
+ nameOrPid : String ,
137
78
call: ( SwiftReflectionContextRef ) throws -> Void ) throws {
138
- let ( inspector, context) = makeReflectionContext ( args : & args )
79
+ let ( inspector, context) = makeReflectionContext ( nameOrPid : nameOrPid )
139
80
defer {
140
81
swift_reflection_destroyReflectionContext ( context)
141
82
inspector. destroyContext ( )
142
83
}
143
84
try call ( context)
144
85
}
145
86
146
- let commandName = argv. popFirst ( )
147
- for command in commands {
148
- if command. name == commandName {
149
- do {
150
- try command. call ( & argv)
151
- } catch let error as SwiftReflectionContextRef . Error {
152
- print ( " Error: \( error. description) " , to: & Std. err)
153
- exit ( 1 )
154
- } catch {
155
- print ( " Unknown error: \( error) " )
87
+ struct Swiftdt : ParsableCommand {
88
+ static let configuration = CommandConfiguration (
89
+ abstract: " Swift runtime debug tool " ,
90
+ subcommands: [
91
+ DumpConformanceCache . self,
92
+ DumpMetadataAllocations . self,
93
+ ] )
94
+ }
95
+
96
+ struct DumpConformanceCache : ParsableCommand {
97
+ static let configuration = CommandConfiguration (
98
+ abstract: " Print the contents of the target's protocol conformance cache. " )
99
+
100
+ @Argument ( help: " The pid or partial name of the target process " )
101
+ var nameOrPid : String
102
+
103
+ func run( ) throws {
104
+ try withReflectionContext ( nameOrPid: nameOrPid) {
105
+ try dumpConformanceCache ( context: $0)
156
106
}
157
- exit ( 0 )
158
107
}
159
108
}
160
109
161
- if let commandName = commandName {
162
- print ( " error: \( executableName) : unknown command \( commandName) " , to: & Std. err)
163
- } else {
164
- print ( " error: \( executableName) : missing command " , to: & Std. err)
110
+ struct DumpMetadataAllocations : ParsableCommand {
111
+ static let configuration = CommandConfiguration (
112
+ abstract: " Print the target's metadata allocations. " )
113
+ @Argument ( help: " The pid or partial name of the target process " )
114
+
115
+ var nameOrPid : String
116
+
117
+ func run( ) throws {
118
+ try withReflectionContext ( nameOrPid: nameOrPid) {
119
+ try dumpMetadataAllocations ( context: $0)
120
+ }
121
+ }
165
122
}
166
- print ( " " , to: & Std. err)
167
- printUsage ( args: & argv)
168
- exit ( EX_USAGE)
123
+
124
+ Swiftdt . main ( )
0 commit comments