Skip to content

Commit f89a842

Browse files
committed
Implement more packet handling, update naming
1 parent c5a5b35 commit f89a842

File tree

11 files changed

+132
-67
lines changed

11 files changed

+132
-67
lines changed

[email protected]

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -120,30 +120,30 @@ let package = Package(
120120
.target(name: "WITExtractor"),
121121
.testTarget(name: "WITExtractorTests", dependencies: ["WITExtractor", "WIT"]),
122122

123-
.target(name: "LLDBRemoteProtocol",
123+
.target(name: "GDBRemoteProtocol",
124124
dependencies: [
125125
.product(name: "NIOCore", package: "swift-nio"),
126126
]
127127
),
128-
.testTarget(name: "LLDBRemoteProtocolTests", dependencies: ["LLDBRemoteProtocol"]),
128+
.testTarget(name: "GDBRemoteProtocolTests", dependencies: ["GDBRemoteProtocol"]),
129129

130130
.target(
131-
name: "WasmKitLLDBHandler",
131+
name: "WasmKitGDBHandler",
132132
dependencies: [
133133
.product(name: "NIOCore", package: "swift-nio"),
134134
"WasmKit",
135-
"LLDBRemoteProtocol",
135+
"GDBRemoteProtocol",
136136
],
137137
),
138138

139139
.executableTarget(
140-
name: "wasmkit-lldb",
140+
name: "wasmkit-gdb-tool",
141141
dependencies: [
142142
.product(name: "ArgumentParser", package: "swift-argument-parser"),
143143
.product(name: "NIOCore", package: "swift-nio"),
144144
.product(name: "NIOPosix", package: "swift-nio"),
145-
"LLDBRemoteProtocol",
146-
"WasmKitLLDBHandler",
145+
"GDBRemoteProtocol",
146+
"WasmKitGDBHandler",
147147
]
148148
),
149149
],

Sources/LLDBRemoteProtocol/CommandDecoder.swift renamed to Sources/GDBRemoteProtocol/CommandDecoder.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ extension ByteBuffer {
1212
}
1313
}
1414

15-
package struct CommandDecoder: ByteToMessageDecoder {
15+
package struct GDBHostCommandDecoder: ByteToMessageDecoder {
1616
enum Error: Swift.Error {
1717
case expectedCommandStart
1818
case unknownCommandKind(String)
1919
case expectedChecksum
2020
case checksumIncorrect
2121
}
2222

23-
package typealias InboundOut = Packet<HostCommand>
23+
package typealias InboundOut = Packet<GDBHostCommand>
2424

2525
private var accummulatedKind = [UInt8]()
2626
private var accummulatedArguments = [UInt8]()
@@ -32,12 +32,16 @@ package struct CommandDecoder: ByteToMessageDecoder {
3232
UInt8(self.accummulatedSum % 256)
3333
}
3434

35-
mutating package func decode(buffer: inout ByteBuffer) throws -> Packet<HostCommand>? {
35+
mutating package func decode(buffer: inout ByteBuffer) throws -> Packet<GDBHostCommand>? {
3636
// Command start delimiters.
37-
guard
38-
buffer.readInteger(as: UInt8.self) == UInt8(ascii: "+")
39-
&& buffer.readInteger(as: UInt8.self) == UInt8(ascii: "$")
37+
let firstStartDelimiter = buffer.readInteger(as: UInt8.self)
38+
let secondStartDelimiter = buffer.readInteger(as: UInt8.self)
39+
guard firstStartDelimiter == UInt8(ascii: "+")
40+
&& secondStartDelimiter == UInt8(ascii: "$")
4041
else {
42+
if let firstStartDelimiter, let secondStartDelimiter {
43+
print("unexpected delimiter: \(Character(UnicodeScalar(firstStartDelimiter)))\(Character(UnicodeScalar(secondStartDelimiter)))")
44+
}
4145
throw Error.expectedCommandStart
4246
}
4347

@@ -74,7 +78,7 @@ package struct CommandDecoder: ByteToMessageDecoder {
7478

7579
let kindString = String(decoding: self.accummulatedKind, as: UTF8.self)
7680

77-
if let commandKind = HostCommand.Kind(rawValue: kindString) {
81+
if let commandKind = GDBHostCommand.Kind(rawValue: kindString) {
7882
buffer.moveReaderIndex(forwardBy: 1)
7983

8084
guard let checksumString = buffer.readString(length: 2),

Sources/LLDBRemoteProtocol/HostCommand.swift renamed to Sources/GDBRemoteProtocol/HostCommand.swift

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
/// See https://lldb.llvm.org/resources/lldbgdbremote.html for more details.
2-
package struct HostCommand: Equatable {
1+
/// See GDB and LLDB remote protocol documentation for more details:
2+
/// * https://sourceware.org/gdb/current/onlinedocs/gdb.html/General-Query-Packets.html
3+
/// * https://lldb.llvm.org/resources/lldbgdbremote.html
4+
package struct GDBHostCommand: Equatable {
35
package enum Kind: Equatable {
46
// Currently listed in the order that LLDB sends them in.
57
case generalRegisters
@@ -9,6 +11,11 @@ package struct HostCommand: Equatable {
911
case isThreadSuffixSupported
1012
case listThreadsInStopReply
1113
case hostInfo
14+
case vContSupportedActions
15+
case isVAttachOrWaitSupported
16+
case enableErrorStrings
17+
case processInfo
18+
case currentThreadID
1219

1320
package init?(rawValue: String) {
1421
switch rawValue {
@@ -24,6 +31,16 @@ package struct HostCommand: Equatable {
2431
self = .listThreadsInStopReply
2532
case "qHostInfo":
2633
self = .hostInfo
34+
case "vCont?":
35+
self = .vContSupportedActions
36+
case "qVAttachOrWaitSupported":
37+
self = .isVAttachOrWaitSupported
38+
case "QEnableErrorStrings":
39+
self = .enableErrorStrings
40+
case "qProcessInfo":
41+
self = .processInfo
42+
case "qC":
43+
self = .currentThreadID
2744
default:
2845
return nil
2946
}
File renamed without changes.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import Foundation
2+
import NIOCore
3+
4+
extension String {
5+
fileprivate var appendedChecksum: String.UTF8View {
6+
"\(self)#\(String(format:"%02X", self.utf8.reduce(0, { $0 + Int($1) }) % 256))".utf8
7+
}
8+
}
9+
10+
package struct GDBTargetResponseEncoder: MessageToByteEncoder {
11+
package init() {}
12+
package func encode(data: TargetResponse, out: inout ByteBuffer) throws {
13+
if !data.isNoAckModeActive {
14+
out.writeInteger(UInt8(ascii: "+"))
15+
}
16+
out.writeInteger(UInt8(ascii: "$"))
17+
18+
switch data.kind {
19+
case .ok:
20+
out.writeBytes("ok#da".utf8)
21+
22+
case .hostInfo(let info):
23+
out.writeBytes(info.map { (key, value) in "\(key):\(value);"}.joined().appendedChecksum)
24+
25+
case .vContSupportedActions(let actions):
26+
out.writeBytes("vCont;\(actions.map(\.rawValue).joined())".appendedChecksum)
27+
28+
case .raw(let str):
29+
out.writeBytes(str.appendedChecksum)
30+
31+
case .empty:
32+
out.writeBytes("".appendedChecksum)
33+
}
34+
}
35+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/// Actions supported in the `vCont` host command.
2+
package enum VContActions: String {
3+
case `continue` = "c"
4+
case continueWithSignal = "C"
5+
case step = "s"
6+
case stepWithSignal = "S"
7+
case stop = "t"
8+
case stepInRange = "r"
9+
}
10+
11+
package struct TargetResponse {
12+
package enum Kind {
13+
case ok
14+
case hostInfo(KeyValuePairs<String, String>)
15+
case vContSupportedActions([VContActions])
16+
case raw(String)
17+
case empty
18+
}
19+
20+
package let kind: Kind
21+
package let isNoAckModeActive: Bool
22+
23+
package init(kind: Kind, isNoAckModeActive: Bool) {
24+
self.kind = kind
25+
self.isNoAckModeActive = isNoAckModeActive
26+
}
27+
}

Sources/LLDBRemoteProtocol/ResponseEncoder.swift

Lines changed: 0 additions & 24 deletions
This file was deleted.

Sources/LLDBRemoteProtocol/TargetResponse.swift

Lines changed: 0 additions & 15 deletions
This file was deleted.

Sources/WasmKitLLDBHandler/WasmKitHandler.swift renamed to Sources/WasmKitGDBHandler/WasmKitHandler.swift

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import LLDBRemoteProtocol
1+
import GDBRemoteProtocol
22
import NIOCore
33
import WasmKit
44

55
import struct Foundation.Date
66

77
package final class WasmKitHandler: ChannelInboundHandler {
8-
package typealias InboundIn = Packet<HostCommand>
8+
package typealias InboundIn = Packet<GDBHostCommand>
99
package typealias OutboundOut = TargetResponse
1010

1111
/// Whether `QStartNoAckMode` command was previously sent.
@@ -24,15 +24,36 @@ package final class WasmKitHandler: ChannelInboundHandler {
2424
switch command.kind {
2525
case .startNoAckMode, .isThreadSuffixSupported, .listThreadsInStopReply:
2626
responseKind = .ok
27+
28+
case .hostInfo:
29+
responseKind = .hostInfo([
30+
"arch": "wasm32",
31+
"ptrsize": "4",
32+
"endian": "little",
33+
"ostype": "wasip1",
34+
"vendor": "WasmKit"
35+
])
36+
2737
case .supportedFeatures:
2838
responseKind = .raw(command.arguments)
29-
default:
39+
40+
case .vContSupportedActions:
41+
responseKind = .vContSupportedActions([.continue, .step, .stop])
42+
43+
case .isVAttachOrWaitSupported, .enableErrorStrings, .processInfo:
44+
responseKind = .empty
45+
46+
case .currentThreadID:
47+
responseKind = .raw("QC 1")
48+
49+
case .generalRegisters, .firstThreadInfo:
3050
fatalError()
3151
}
3252

3353
context.writeAndFlush(
3454
wrapOutboundOut(.init(kind: responseKind, isNoAckModeActive: self.isNoAckModeActive)),
35-
promise: nil)
55+
promise: nil
56+
)
3657
if command.kind == .startNoAckMode {
3758
self.isNoAckModeActive = true
3859
}

Sources/wasmkit-lldb/Entrypoint.swift renamed to Sources/wasmkit-gdb-tool/Entrypoint.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import ArgumentParser
2-
import LLDBRemoteProtocol
2+
import GDBRemoteProtocol
33
import NIOCore
44
import NIOPosix
5-
import WasmKitLLDBHandler
5+
import WasmKitGDBHandler
66

77
@main
88
struct Entrypoint: ParsableCommand {
@@ -24,8 +24,8 @@ struct Entrypoint: ParsableCommand {
2424
// make sure to instantiate your `ChannelHandlers` inside of
2525
// the closure as it will be invoked once per connection.
2626
try channel.pipeline.syncOperations.addHandlers([
27-
ByteToMessageHandler(CommandDecoder()),
28-
MessageToByteHandler(ResponseEncoder()),
27+
ByteToMessageHandler(GDBHostCommandDecoder()),
28+
MessageToByteHandler(GDBTargetResponseEncoder()),
2929
WasmKitHandler(),
3030
])
3131
}

0 commit comments

Comments
 (0)