diff --git a/openspec/changes/whitemagic-foundation/tasks.md b/openspec/changes/whitemagic-foundation/tasks.md index 5fac5ab..4d3aa53 100644 --- a/openspec/changes/whitemagic-foundation/tasks.md +++ b/openspec/changes/whitemagic-foundation/tasks.md @@ -9,9 +9,9 @@ ## 2. Core Memory Access (spec: memory-access) - [x] 2.1 Add tests for `MarshalCache`: blittable size, marshal-required flag, IsIntPtr, computed-once behavior -- [x] 2.2 Implement `WhiteMagic/MarshalCache.cs` to pass 2.1 +- [x] 2.2 Implement `WhiteMagic/MarshalCache.cs` to pass 2.1. **Deviation (review):** split `Size` (managed `Unsafe.SizeOf`, blittable/`MemoryMarshal` path) from `MarshalSize` (`Marshal.SizeOf`, marshal path). A single size mis-sized structs whose unmanaged width differs — a `bool` field (managed 1 / unmanaged 4) over-read the blittable path; an inline `ByValTStr`/`ByValArray` under-sized the marshal path and overran the pinned buffer (heap corruption on write). `MemoryBase` now picks per `TypeRequiresMarshal` at all four IO sites. Unused fields (`SizeU`, `IsIntPtr`, `TypeCode`, `RealType`) dropped. - [x] 2.3 Add tests for `MemoryBase` abstract contract + `ExternalReader` round-trip (`Read`/`Write`, arrays) using the current process as target -- [x] 2.4 Implement `WhiteMagic/MemoryBase.cs` (abstract) and `WhiteMagic/ExternalReader.cs` to pass 2.3 +- [x] 2.4 Implement `WhiteMagic/MemoryBase.cs` (abstract) and `WhiteMagic/ExternalReader.cs` to pass 2.3. **Deviation (review):** shared RPM/WPM extracted to `WhiteMagic/RpmHelper.cs` so `ExternalReader` and `InProcessReader` stay byte-consistent — partial reads honored (returns exactly `bytesRead`), write returns actual bytes / 0 on total failure; `InProcessReader` guards `MainModule` like `ExternalReader`. - [x] 2.5 Add tests for string read/write with encoding, null-terminator stop, and max length - [x] 2.6 Implement `ReadString`/`WriteString` on `MemoryBase` to pass 2.5 - [x] 2.7 Add tests for relative/absolute addressing (`GetAbsolute`/`GetRelative`, `isRelative` flag) @@ -21,15 +21,15 @@ ## 3. Managed Assembler (spec: managed-assembler) -- [ ] 3.1 Add tests for `EmitU8`/`EmitU32`/`EmitU64` little-endian primitives -- [ ] 3.2 Implement `WhiteMagic/Assembly/StubAssembler.cs` emitters + `IAssembler` interface to pass 3.1 -- [ ] 3.3 Add tests for x86 cdecl stub encoding (reverse push, call, `add esp, N*4`, ret) with known byte expectations -- [ ] 3.4 Implement x86 cdecl stub to pass 3.3 -- [ ] 3.5 Add tests for stdcall (no caller cleanup), thiscall (ecx = this), fastcall (ecx/edx) x86 stubs -- [ ] 3.6 Implement x86 stdcall/thiscall/fastcall stubs to pass 3.5 -- [ ] 3.7 Add tests for x64 stub argument-register placement and call -- [ ] 3.8 Implement x64 stub to pass 3.7 -- [ ] 3.9 Confirm no FASM/`ManagedFasm` reference exists in `WhiteMagic` output (assert via a test that scans loaded references) +- [x] 3.1 Add tests for `EmitU8`/`EmitU32`/`EmitU64` little-endian primitives +- [x] 3.2 Implement `WhiteMagic/Assembly/StubAssembler.cs` emitters + `IAssembler` interface to pass 3.1 +- [x] 3.3 Add tests for x86 cdecl stub encoding (reverse push, call, `add esp, N*4`, ret) with known byte expectations +- [x] 3.4 Implement x86 cdecl stub to pass 3.3 +- [x] 3.5 Add tests for stdcall (no caller cleanup), thiscall (ecx = this), fastcall (ecx/edx) x86 stubs +- [x] 3.6 Implement x86 stdcall/thiscall/fastcall stubs to pass 3.5 +- [x] 3.7 Add tests for x64 stub argument-register placement and call +- [x] 3.8 Implement x64 stub to pass 3.7. **Deviation (review):** `BuildCallStub` takes `nuint[]` (was `uint[]`). x64 stub is Microsoft-x64-ABI compliant: allocates 32-byte shadow space, keeps 16-byte stack alignment at the inner `call` (frame `K ≡ 8 (mod 16)`, `K ≥ 0x20 + 8·stackArgs`), loads RCX/RDX/R8/R9 with full 64-bit `imm64` (no >4 GiB pointer truncation), and writes stack args above the shadow window (no return-address clobber). x86 rejects args > `uint.MaxValue`. Argument count bounded by `MaxArguments` (256) to keep frame arithmetic overflow-free. **Byte-level tests only — a live-execution test (5-arg + SSE callee via `CreateRemoteThread`) is still needed to prove the ABI at runtime.** +- [x] 3.9 Confirm no FASM/`ManagedFasm` reference exists in `WhiteMagic` output (assert via a test that scans loaded references) ## 4. Crash-Safe Execution Slice (spec: remote-execution, function-hooking)