11import GDBRemoteProtocol
22import Logging
3+ import NIOCore
4+ import NIOFileSystem
35import Synchronization
46import SystemPackage
57import WasmKit
8+ import WasmKitWASI
9+
10+ extension BinaryInteger {
11+ init ? ( hexEncoded: Substring ) {
12+ var result = Self . zero
13+ for (offset, element) in hexEncoded. reversed ( ) . enumerated ( ) {
14+ guard let digit = element. hexDigitValue else { return nil }
15+ result += Self ( digit) << ( offset * 4 )
16+ }
17+
18+ self = result
19+ }
20+ }
621
722package actor WasmKitGDBHandler {
823 enum Error : Swift . Error {
924 case unknownTransferArguments
25+ case unknownReadMemoryArguments
26+ case entrypointFunctionNotFound
1027 }
1128
29+ private let wasmBinary : ByteBuffer
1230 private let module : Module
1331 private let moduleFilePath : FilePath
1432 private let logger : Logger
1533 private let debuggerExecution : DebuggerExecution
1634 private let instance : Instance
35+ private let entrypointFunction : Function
36+ private let functionsRLE : [ ( wasmAddress: Int , iSeqAddress: Int ) ] = [ ]
1737
18- package init ( logger: Logger , moduleFilePath: FilePath ) throws {
38+ package init ( logger: Logger , moduleFilePath: FilePath ) async throws {
1939 self . logger = logger
20- self . module = try parseWasm ( filePath: moduleFilePath)
40+
41+ self . wasmBinary = try await FileSystem . shared. withFileHandle ( forReadingAt: moduleFilePath) {
42+ try await $0. readToEnd ( maximumSizeAllowed: . unlimited)
43+ }
44+
45+ self . module = try parseWasm ( bytes: . init( buffer: self . wasmBinary) )
2146 self . moduleFilePath = moduleFilePath
2247 let store = Store ( engine: Engine ( ) )
2348 self . debuggerExecution = DebuggerExecution ( store: store)
24- self . instance = try module. instantiate ( store: store)
49+
50+ var imports = Imports ( )
51+ let wasi = try WASIBridgeToHost ( )
52+ wasi. link ( to: & imports, store: store)
53+ self . instance = try module. instantiate ( store: store, imports: imports)
54+
55+ guard case . function( let entrypointFunction) = self . instance. exports [ " _start " ] else {
56+ throw Error . entrypointFunctionNotFound
57+ }
58+ self . entrypointFunction = entrypointFunction
2559 }
2660
2761 package func handle( command: GDBHostCommand ) throws -> GDBTargetResponse {
@@ -47,7 +81,7 @@ package actor WasmKitGDBHandler {
4781 ] )
4882
4983 case . supportedFeatures:
50- responseKind = . raw ( " qXfer:libraries:read+;PacketSize=1000; " )
84+ responseKind = . string ( " qXfer:libraries:read+;PacketSize=1000; " )
5185
5286 case . vContSupportedActions:
5387 responseKind = . vContSupportedActions( [ . continue, . step] )
@@ -65,13 +99,13 @@ package actor WasmKitGDBHandler {
6599 ] )
66100
67101 case . currentThreadID:
68- responseKind = . raw ( " QC1 " )
102+ responseKind = . string ( " QC1 " )
69103
70104 case . firstThreadInfo:
71- responseKind = . raw ( " m1 " )
105+ responseKind = . string ( " m1 " )
72106
73107 case . subsequentThreadInfo:
74- responseKind = . raw ( " l " )
108+ responseKind = . string ( " l " )
75109
76110 case . targetStatus:
77111 responseKind = . keyValuePairs( [
@@ -93,12 +127,12 @@ package actor WasmKitGDBHandler {
93127 " generic " : " pc " ,
94128 ] )
95129 } else {
96- responseKind = . raw ( " E45 " )
130+ responseKind = . string ( " E45 " )
97131 }
98132
99133 case . transfer:
100134 if command. arguments. starts ( with: " libraries:read: " ) {
101- responseKind = . raw (
135+ responseKind = . string (
102136 """
103137 l<library-list>
104138 <library name= " \( self . moduleFilePath. string) " ><section address= " 0x4000000000000000 " /></library>
@@ -109,7 +143,20 @@ package actor WasmKitGDBHandler {
109143 }
110144
111145 case . readMemory:
112- responseKind = . empty
146+ let argumentsArray = command. arguments. split ( separator: " , " )
147+ guard
148+ argumentsArray. count == 2 ,
149+ let address = UInt64 ( hexEncoded: argumentsArray [ 0 ] ) ,
150+ var length = Int ( hexEncoded: argumentsArray [ 1 ] )
151+ else { throw Error . unknownReadMemoryArguments }
152+
153+ let binaryOffset = Int ( address - 0x4000000000000000 )
154+
155+ if binaryOffset + length > wasmBinary. readableBytes {
156+ length = wasmBinary. readableBytes - binaryOffset
157+ }
158+
159+ responseKind = . hexEncodedBinary( wasmBinary. readableBytesView [ binaryOffset..< ( binaryOffset + length) ] )
113160
114161 case . wasmCallStack:
115162 print ( self . debuggerExecution. captureBacktrace ( ) )
0 commit comments