|
1 | 1 | #if WasmDebuggingSupport |
2 | | - |
3 | | - extension [Int] { |
4 | | - /// Uses binary search to find an element in `self` that's next closest to a given value. |
5 | | - /// - Parameter value: the array element to search for or to use as a baseline when searching. |
6 | | - /// - Returns: array element `result`, where `result - value` is the smallest possible, while |
7 | | - /// `result > value` also holds. |
8 | | - package func binarySearch(nextClosestTo value: Int) -> Int? { |
9 | | - switch self.count { |
10 | | - case 0: |
11 | | - return nil |
12 | | - default: |
13 | | - var slice = self[0..<self.count] |
14 | | - while slice.count > 1 { |
15 | | - let middle = (slice.endIndex - slice.startIndex) / 2 |
16 | | - if slice[middle] < value { |
17 | | - // Not found anything in the lower half, assigning higher half to `slice`. |
18 | | - slice = slice[(middle + 1)..<slice.endIndex] |
19 | | - } else { |
20 | | - // Not found anything in the higher half, assigning lower half to `slice`. |
21 | | - slice = slice[slice.startIndex..<middle] |
22 | | - } |
23 | | - } |
24 | | - |
25 | | - return self[slice.startIndex] |
26 | | - } |
27 | | - } |
28 | | - } |
29 | | - |
30 | | - extension Instance { |
31 | | - /// Computes an address of WasmKit's iseq bytecode instruction that matches a given Wasm instruction address. |
32 | | - /// - Parameter address: the Wasm instruction to find a mapping for. |
33 | | - /// - Returns: A tuple with an address of found iseq instruction and the original Wasm instruction or next |
34 | | - /// closest match if no direct match was found. |
35 | | - fileprivate func findIseq(forWasmAddress address: Int) throws(Debugger.Error) -> (iseq: Pc, wasm: Int) { |
36 | | - // Look in the main mapping |
37 | | - if let iseq = handle.wasmToIseqMapping[address] { |
38 | | - return (iseq, address) |
39 | | - } |
40 | | - |
41 | | - // If nothing found, find the closest Wasm address using binary search |
42 | | - guard let nextAddress = handle.wasmMappings.binarySearch(nextClosestTo: address), |
43 | | - // Look in the main mapping again with the next closest address if binary search produced anything |
44 | | - let iseq = handle.wasmToIseqMapping[nextAddress] |
45 | | - else { |
46 | | - throw Debugger.Error.noInstructionMappingAvailable(address) |
47 | | - } |
48 | | - |
49 | | - return (iseq, nextAddress) |
50 | | - } |
51 | | - } |
52 | | - |
53 | 2 | /// User-facing debugger state driven by a debugger host. This implementation has no knowledge of the exact |
54 | 3 | /// debugger protocol, which allows any protocol implementation or direct API users to be layered on top if needed. |
55 | 4 | package struct Debugger: ~Copyable { |
|
140 | 89 | return |
141 | 90 | } |
142 | 91 |
|
143 | | - let (iseq, wasm) = try self.instance.findIseq(forWasmAddress: address) |
| 92 | + guard let (iseq, wasm) = try self.instance.handle.instructionMapping.findIseq(forWasmAddress: address) else { |
| 93 | + throw Error.noInstructionMappingAvailable(address) |
| 94 | + } |
144 | 95 |
|
145 | 96 | self.breakpoints[wasm] = iseq.pointee |
146 | 97 | iseq.pointee = Instruction.breakpoint.headSlot(threadingModel: self.threadingModel) |
|
156 | 107 | return |
157 | 108 | } |
158 | 109 |
|
159 | | - let (iseq, wasm) = try self.instance.findIseq(forWasmAddress: address) |
| 110 | + guard let (iseq, wasm) = try self.instance.handle.instructionMapping.findIseq(forWasmAddress: address) else { |
| 111 | + throw Error.noInstructionMappingAvailable(address) |
| 112 | + } |
160 | 113 |
|
161 | 114 | self.breakpoints[wasm] = nil |
162 | 115 | iseq.pointee = oldCodeSlot |
|
216 | 169 | } |
217 | 170 | } catch let breakpoint as Execution.Breakpoint { |
218 | 171 | let pc = breakpoint.pc |
219 | | - guard let wasmPc = self.instance.handle.iseqToWasmMapping[pc] else { |
| 172 | + guard let wasmPc = self.instance.handle.instructionMapping.findWasm(forIseqAddress: pc) else { |
220 | 173 | throw Error.noReverseInstructionMappingAvailable(pc) |
221 | 174 | } |
222 | 175 |
|
|
232 | 185 | } |
233 | 186 |
|
234 | 187 | var result = Execution.captureBacktrace(sp: currentBreakpoint.iseq.sp, store: self.store).symbols.compactMap { |
235 | | - return self.instance.handle.iseqToWasmMapping[$0.address] |
| 188 | + return self.instance.handle.instructionMapping.findWasm(forIseqAddress: $0.address) |
236 | 189 | } |
237 | 190 | result.append(currentBreakpoint.wasmPc) |
238 | 191 |
|
|
0 commit comments