Recover native trig spatial and VM pointer contracts
Browse files- docs/FINDINGS.md +6 -0
- docs/PROVISIONAL_TODO.md +1 -1
- docs/RESEARCH_LEDGER.md +4 -0
- docs/REVERSE_ENGINEERING_TODO.md +5 -0
- docs/research/CHAT_CROSSHAIR.md +2 -0
- docs/research/CHAT_LOCATIONS.md +2 -0
- docs/research/NATIVE_SPATIAL.md +50 -0
- docs/research/README.md +4 -1
- docs/research/native-spatial.json +0 -0
- scripts/analyze_binaries.py +1 -1
- scripts/analyze_native_spatial.py +119 -0
- scripts/test_native_spatial.py +81 -0
docs/FINDINGS.md
CHANGED
|
@@ -282,3 +282,9 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
|
|
| 282 |
**F-071 — Observed crosshair trace arguments:** service 24 receives result/origin/NULL/NULL/endpoint pointers, sender-record field 140 and mask 1. G_TRACE remains a pinned upstream candidate; full shipped structure/service semantics and runtime collision are unverified. [AIM-002](research/CHAT_CROSSHAIR.md).
|
| 283 |
|
| 284 |
**F-072 — Observed crosshair result handling:** trace word +4 exactly 1 requests unknown then sender location. Other observed words build a cache-cleared temporary object from result +12/+16/+20; a subsequent comparison return zero triggers sender fallback. Calls/returns remain synthetic placeholders or isolated supplied inputs, so actual endpoint output/failure behavior is open. [AIM-003](research/CHAT_CROSSHAIR.md).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 282 |
**F-071 — Observed crosshair trace arguments:** service 24 receives result/origin/NULL/NULL/endpoint pointers, sender-record field 140 and mask 1. G_TRACE remains a pinned upstream candidate; full shipped structure/service semantics and runtime collision are unverified. [AIM-002](research/CHAT_CROSSHAIR.md).
|
| 283 |
|
| 284 |
**F-072 — Observed crosshair result handling:** trace word +4 exactly 1 requests unknown then sender location. Other observed words build a cache-cleared temporary object from result +12/+16/+20; a subsequent comparison return zero triggers sender fallback. Calls/returns remain synthetic placeholders or isolated supplied inputs, so actual endpoint output/failure behavior is open. [AIM-003](research/CHAT_CROSSHAIR.md).
|
| 285 |
+
|
| 286 |
+
**F-073 — Confirmed Linux trig/spatial destinations:** both ELF64 engines map services 103/104 to sinf/cosf, 24 to SV_Trace, 26 to SV_inPVS and 32 to SV_AreaEntities. Trig returns single-precision integer bit patterns; static transport mappings now corroborate prior QVM candidates. Runtime and other-platform equivalence remain open. [NAT-001](research/NATIVE_SPATIAL.md).
|
| 287 |
+
|
| 288 |
+
**F-074 — Observed VM pointer branch distinction:** raw zero/currentVM NULL returns NULL; other arguments use direct base addition or signed-extended 32-bit masking followed by addition. A nonzero argument that masks to zero can return the data base. Paired synthetic instruction traces do not establish legal allocation/mask invariants. [NAT-002](research/NATIVE_SPATIAL.md).
|
| 289 |
+
|
| 290 |
+
**F-075 — Observed native spatial structure:** trace NULL extents reference zero-fill storage and return copies span 56 bytes; PVS combines cluster bits with area connectivity. Area queries write four-byte indices and test equality with capacity before warning. Full fields/geometry/portals/tree ownership and runtime behavior remain open. [NAT-003](research/NATIVE_SPATIAL.md).
|
docs/PROVISIONAL_TODO.md
CHANGED
|
@@ -33,7 +33,7 @@ For implementation items, the minimum done condition is a documented contract, a
|
|
| 33 |
|
| 34 |
### First research batch
|
| 35 |
|
| 36 |
-
Progress: [RE-232–234 / TIME-001–003](research/FRAME_TIMING.md) now cover Linux ELF64 elapsed modification, event sources and pause predicates. The [RE-237–239 follow-up](research/EVENT_QUEUES.md) resolves the pause-field address/bot chain and adds queue/journal evidence. The [RE-241–243 announcement pass](research/AUTH_ANNOUNCEMENTS.md) recovers label tables and recipient paths; The [RE-245–247 cvar pass](research/GAME_CVARS.md) adds all 126 main registration rows and resolves auth_verbosity/callers. The [RE-249–251 change pass](research/CVAR_CHANGES.md) adds cache/notification behavior, four numeric correction branches and direct registration coverage. The [RE-253–255 query pass](research/AUTH_QUERIES.md) adds selector helpers, command-role routing and internal authentication modes. The [RE-257–259 bounds/entry pass](research/SELECTOR_BOUNDS.md) adds integer parsing, selector storage/count evidence and native/QVM/chat route connections. The [RE-261–263 chat pass](research/CHAT_PATHS.md) adds native command metadata/filter evidence and bounded message/recipient paths, including the documented argument-mapping correction. The [RE-265–267 delivery pass](research/CHAT_DELIVERY.md) adds bounded dead-chat predicates, formatter argument routing and echo/fanout calls. The [RE-269–271 expansion pass](research/CHAT_EXPANSION.md) adds marker states, twelve key comparisons and health/momo branches. The [RE-273–275 item/time pass](research/CHAT_ITEMS_TIME.md) adds packed ammunition fields, sampled names and countdown branches. The [RE-277–279 location pass](research/CHAT_LOCATIONS.md) adds leader selection, cache/format boundaries and location-list/spatial evidence. The [RE-281–283 crosshair pass](research/CHAT_CROSSHAIR.md) adds finite geometry fixtures, trace arguments and result routing. PROV-002 remains open for full output/reset coverage. PROV-001 remains open for complete scheduling and platform coverage.
|
| 37 |
|
| 38 |
Start with the open questions raised by the current binary evidence. These tasks depend on the linked reports, not on a working rewrite.
|
| 39 |
|
|
|
|
| 33 |
|
| 34 |
### First research batch
|
| 35 |
|
| 36 |
+
Progress: [RE-232–234 / TIME-001–003](research/FRAME_TIMING.md) now cover Linux ELF64 elapsed modification, event sources and pause predicates. The [RE-237–239 follow-up](research/EVENT_QUEUES.md) resolves the pause-field address/bot chain and adds queue/journal evidence. The [RE-241–243 announcement pass](research/AUTH_ANNOUNCEMENTS.md) recovers label tables and recipient paths; The [RE-245–247 cvar pass](research/GAME_CVARS.md) adds all 126 main registration rows and resolves auth_verbosity/callers. The [RE-249–251 change pass](research/CVAR_CHANGES.md) adds cache/notification behavior, four numeric correction branches and direct registration coverage. The [RE-253–255 query pass](research/AUTH_QUERIES.md) adds selector helpers, command-role routing and internal authentication modes. The [RE-257–259 bounds/entry pass](research/SELECTOR_BOUNDS.md) adds integer parsing, selector storage/count evidence and native/QVM/chat route connections. The [RE-261–263 chat pass](research/CHAT_PATHS.md) adds native command metadata/filter evidence and bounded message/recipient paths, including the documented argument-mapping correction. The [RE-265–267 delivery pass](research/CHAT_DELIVERY.md) adds bounded dead-chat predicates, formatter argument routing and echo/fanout calls. The [RE-269–271 expansion pass](research/CHAT_EXPANSION.md) adds marker states, twelve key comparisons and health/momo branches. The [RE-273–275 item/time pass](research/CHAT_ITEMS_TIME.md) adds packed ammunition fields, sampled names and countdown branches. The [RE-277–279 location pass](research/CHAT_LOCATIONS.md) adds leader selection, cache/format boundaries and location-list/spatial evidence. The [RE-281–283 crosshair pass](research/CHAT_CROSSHAIR.md) adds finite geometry fixtures, trace arguments and result routing. The [RE-285–287 native spatial pass](research/NATIVE_SPATIAL.md) confirms Linux trig/spatial services, VM pointer branches and collision/query evidence. PROV-002 remains open for full output/reset coverage. PROV-001 remains open for complete scheduling and platform coverage.
|
| 37 |
|
| 38 |
Start with the open questions raised by the current binary evidence. These tasks depend on the linked reports, not on a working rewrite.
|
| 39 |
|
docs/RESEARCH_LEDGER.md
CHANGED
|
@@ -145,3 +145,7 @@ Completed RE-277–279 bounded/static milestones with `analyze_chat_locations.py
|
|
| 145 |
## 2026-10-11 — Crosshair geometry and result routing
|
| 146 |
|
| 147 |
Completed bounded milestones RE-281–283 with `analyze_chat_crosshair.py`: five dead gates, three origin/height cases, five supplied cardinal basis/endpoint cases, exact trace arguments, three result paths and three isolated comparison-return paths. AIM-001–003/F-070–072 separate finite straight-line binary32 arithmetic from native trig/collision and explicit zero callee-return placeholders. Eight tests check basis/origin/endpoints, seven-word ABI requests, exact-one status and temporary writes, fallback predicates and fail-closed float/memory/opcode/copy bounds. Added a separate restricted arithmetic evaluator without expanding the integer evaluator's domain. RE-272/280 remain open; RE-284 tracks full layout/float/temporary-object/output/runtime/platform contracts. No original process/full QVM or recorded callee executes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
## 2026-10-11 — Crosshair geometry and result routing
|
| 146 |
|
| 147 |
Completed bounded milestones RE-281–283 with `analyze_chat_crosshair.py`: five dead gates, three origin/height cases, five supplied cardinal basis/endpoint cases, exact trace arguments, three result paths and three isolated comparison-return paths. AIM-001–003/F-070–072 separate finite straight-line binary32 arithmetic from native trig/collision and explicit zero callee-return placeholders. Eight tests check basis/origin/endpoints, seven-word ABI requests, exact-one status and temporary writes, fallback predicates and fail-closed float/memory/opcode/copy bounds. Added a separate restricted arithmetic evaluator without expanding the integer evaluator's domain. RE-272/280 remain open; RE-284 tracks full layout/float/temporary-object/output/runtime/platform contracts. No original process/full QVM or recorded callee executes.
|
| 148 |
+
|
| 149 |
+
## 2026-10-11 — Native trig/spatial service and pointer evidence
|
| 150 |
+
|
| 151 |
+
Completed bounded/static RE-285–287 with `analyze_native_spatial.py`: ten complete case paths, twelve helper graphs, eighteen synthetic VM_ArgPtr instruction traces, explicit zero-fill extent origin, file-backed trace constants and capacity warning strings. NAT-001–003/F-073–075 confirm shipped Linux service destinations while retaining all-platform/runtime uncertainty and the distinction between zero-fill initialization and observed runtime contents. Seven tests check mappings/float transport, conversion counts, pointer branches/failure bounds, case boundaries and spatial static gates/copy/index evidence. RE-284 remains open; RE-288 tracks VM allocation, complete collision/PVS/tree/layout and original-runtime/platform requirements. No original process or native callee executes.
|
docs/REVERSE_ENGINEERING_TODO.md
CHANGED
|
@@ -337,3 +337,8 @@ Purpose: turn the supplied installation into an evidence-backed specification of
|
|
| 337 |
- [x] RE-282 Recover exact seven-word crosshair trace argument contract and supplied field-140 forwarding ([AIM-002](research/CHAT_CROSSHAIR.md)).
|
| 338 |
- [x] RE-283 Recover trace offset-4 exact-one branch, endpoint temporary-object/cache-clear writes and isolated comparison-controlled sender fallback ([AIM-003](research/CHAT_CROSSHAIR.md)).
|
| 339 |
- [ ] RE-284 Confirm native trig services, full record/vector/trace layouts, float exceptional/angle domains, temporary-object requirements, location/comparison/default composition, collision masks and original-runtime/platform fixtures.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 337 |
- [x] RE-282 Recover exact seven-word crosshair trace argument contract and supplied field-140 forwarding ([AIM-002](research/CHAT_CROSSHAIR.md)).
|
| 338 |
- [x] RE-283 Recover trace offset-4 exact-one branch, endpoint temporary-object/cache-clear writes and isolated comparison-controlled sender fallback ([AIM-003](research/CHAT_CROSSHAIR.md)).
|
| 339 |
- [ ] RE-284 Confirm native trig services, full record/vector/trace layouts, float exceptional/angle domains, temporary-object requirements, location/comparison/default composition, collision masks and original-runtime/platform fixtures.
|
| 340 |
+
|
| 341 |
+
- [x] RE-285 Confirm both Linux ELF64 trig/spatial native service destinations and exact pointer/scalar/float-bit transport paths ([NAT-001](research/NATIVE_SPATIAL.md)).
|
| 342 |
+
- [x] RE-286 Recover bounded native VM_ArgPtr NULL/direct/mask/signed-extension branches with paired instruction traces ([NAT-002](research/NATIVE_SPATIAL.md)).
|
| 343 |
+
- [x] RE-287 Recover static NULL trace extents, 56-byte result-copy span, PVS/area gates and area-query index/capacity evidence ([NAT-003](research/NATIVE_SPATIAL.md)).
|
| 344 |
+
- [ ] RE-288 Compare other-platform dispatch, libm/float exception semantics, VM mask/allocation lifetime, full trace/collision fields/internals, PVS/portals/tree/index ordering and original map/runtime fixtures.
|
docs/research/CHAT_CROSSHAIR.md
CHANGED
|
@@ -55,3 +55,5 @@ The wrapper return is discarded. Next helper **36306** receives the shared buffe
|
|
| 55 |
## Remaining work and Rust dependencies
|
| 56 |
|
| 57 |
RE-281–283 cover bounded geometry, trace arguments and result routing. RE-272/280 remain open; RE-284 tracks native service-103/104 trig identity/accuracy, real record/vector/trace layouts, exceptional float and angle domains, full temporary-object memory requirements, location/comparison/default composition, collision/content masks and original-runtime/platform fixtures. Rust crosshair text needs both sender and endpoint location routes, exact status predicates and validated coordinate/trace contracts before claiming gameplay parity.
|
|
|
|
|
|
|
|
|
| 55 |
## Remaining work and Rust dependencies
|
| 56 |
|
| 57 |
RE-281–283 cover bounded geometry, trace arguments and result routing. RE-272/280 remain open; RE-284 tracks native service-103/104 trig identity/accuracy, real record/vector/trace layouts, exceptional float and angle domains, full temporary-object memory requirements, location/comparison/default composition, collision/content masks and original-runtime/platform fixtures. Rust crosshair text needs both sender and endpoint location routes, exact status predicates and validated coordinate/trace contracts before claiming gameplay parity.
|
| 58 |
+
|
| 59 |
+
The [NAT-001–003 follow-up](NATIVE_SPATIAL.md) confirms the shipped Linux ELF64 sinf/cosf and trace/PVS/area-query destinations and recovers VM-pointer/native spatial evidence. Earlier upstream-candidate limitations are narrowed for those mappings; full layout/geometry/runtime and other-platform parity remain open under RE-284/288.
|
docs/research/CHAT_LOCATIONS.md
CHANGED
|
@@ -48,3 +48,5 @@ The [pinned ABI candidate report](qvm/qagame.abi-candidates.json), checked again
|
|
| 48 |
RE-277–279 record these bounded/static milestones; RE-272 remains open for full substitution behavior. RE-280 tracks leader-flag/state writers, count/slot invariants, caller failure/default behavior, cache writers/expiry/reset, raw class tag derivation, linked-field ownership, full floating-point/box/PVS selection, configstring clients and original-runtime/platform fixtures. Rust location lookup needs explicit cache/ordering/tie rules and ownership backed by that evidence; a generic nearest-point search would not reproduce the observed two-stage control flow by itself.
|
| 49 |
|
| 50 |
The [AIM-001–003 follow-up](CHAT_CROSSHAIR.md) recovers the crosshair caller's geometry/trace/result routes. Full spatial services, caller output and runtime behavior remain open under RE-280/284.
|
|
|
|
|
|
|
|
|
| 48 |
RE-277–279 record these bounded/static milestones; RE-272 remains open for full substitution behavior. RE-280 tracks leader-flag/state writers, count/slot invariants, caller failure/default behavior, cache writers/expiry/reset, raw class tag derivation, linked-field ownership, full floating-point/box/PVS selection, configstring clients and original-runtime/platform fixtures. Rust location lookup needs explicit cache/ordering/tie rules and ownership backed by that evidence; a generic nearest-point search would not reproduce the observed two-stage control flow by itself.
|
| 49 |
|
| 50 |
The [AIM-001–003 follow-up](CHAT_CROSSHAIR.md) recovers the crosshair caller's geometry/trace/result routes. Full spatial services, caller output and runtime behavior remain open under RE-280/284.
|
| 51 |
+
|
| 52 |
+
The [NAT-001–003 follow-up](NATIVE_SPATIAL.md) confirms the shipped Linux ELF64 sinf/cosf and trace/PVS/area-query destinations and recovers VM-pointer/native spatial evidence. Earlier upstream-candidate limitations are narrowed for those mappings; full layout/geometry/runtime and other-platform parity remain open under RE-284/288.
|
docs/research/NATIVE_SPATIAL.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Native trigonometry, spatial services and VM pointers
|
| 2 |
+
|
| 3 |
+
Static pass, 2026-10-11. Reproduce with `python3 scripts/analyze_native_spatial.py`; check with `python3 scripts/test_native_spatial.py`. [Generated evidence](native-spatial.json) verifies both supplied Linux ELF64 original/disassembly hashes, rereads native switch tables, retains complete selected case paths and six helper graphs per image, and evaluates eighteen synthetic VM_ArgPtr paths. No original process or native callee executes. Windows, macOS and Linux i386 parity remain open. These findings extend [crosshair](CHAT_CROSSHAIR.md) and [location](CHAT_LOCATIONS.md) recovery.
|
| 4 |
+
|
| 5 |
+
## NAT-001: confirmed shipped service destinations and float transport
|
| 6 |
+
|
| 7 |
+
Both Linux 64-bit engines, client and dedicated, have these actual SV_GameSystemCalls destinations:
|
| 8 |
+
|
| 9 |
+
| Service | QVM encoded CALL | Native destination | VM_ArgPtr calls |
|
| 10 |
+
| ---: | ---: | --- | ---: |
|
| 11 |
+
| 24 | -25 | SV_Trace | 5 |
|
| 12 |
+
| 26 | -27 | SV_inPVS | 2 |
|
| 13 |
+
| 32 | -33 | SV_AreaEntities | 3 |
|
| 14 |
+
| 103 | -104 | sinf@plt | 0 |
|
| 15 |
+
| 104 | -105 | cosf@plt | 0 |
|
| 16 |
+
|
| 17 |
+
The collector extends each case beyond the older 24-instruction dispatch snippet to its terminal transfer. Unexpected branches, missing addresses or unbounded case paths fail closed. These mappings are confirmed in shipped Linux code rather than inferred solely from upstream enums; runtime semantics and other images remain separate requirements.
|
| 18 |
+
|
| 19 |
+
The trig cases load a **single-precision word from native argument-array offset 8** into xmm0, call sinf/cosf, store the float result to a four-byte stack slot and return that slot's integer bit pattern through EAX followed by signed extension (CLTQ). This transports float bits rather than converting the result numerically to an integer. The previous crosshair paired-output sin/cos interpretation is now corroborated for these Linux engines. Actual libm execution, rounding/exception behavior and noncardinal output comparisons remain unverified.
|
| 20 |
+
|
| 21 |
+
Trace case 24 converts its five pointers (result, start, mins, maxs, end) through VM_ArgPtr, forwards the two scalar words through 32-bit argument registers/stack, appends an additional native argument **zero**, calls SV_Trace and clears EAX for the syscall return. The observed crosshair mask 1 and field-140 scalar are therefore forwarded to the trace layer, not interpreted by this dispatcher. Case 26 converts its two position pointers; case 32 converts mins/maxs/output-list and forwards maximum count through ECX, returning a signed-extended result count.
|
| 22 |
+
|
| 23 |
+
## NAT-002: actual VM_ArgPtr branches
|
| 24 |
+
|
| 25 |
+
The full sixteen-instruction helper in each engine has the same observed logic over native currentVM fields:
|
| 26 |
+
|
| 27 |
+
- Raw argument zero returns NULL immediately.
|
| 28 |
+
- Nonzero argument with currentVM NULL also returns NULL.
|
| 29 |
+
- If currentVM word at **0x58** is nonzero, return **data base at 0x90 + raw argument** using 64-bit addition.
|
| 30 |
+
- Otherwise load the mask at **0x98** as a signed 32-bit word, extend it to 64 bits, AND with the argument, then add data base 0x90.
|
| 31 |
+
|
| 32 |
+
The collector's restricted interpreter follows these real instruction addresses, supports only the observed register/memory/test/branch/add/mask/return forms, rejects unknown operations/reads and has a step bound. currentVM and its fields are explicitly supplied synthetic inputs. It is not a general native emulator or a proof of valid mask/allocation invariants.
|
| 33 |
+
|
| 34 |
+
Nine fixtures per image cover NULL argument/currentVM, direct addition, positive mask, all-ones signed mask, negative argument and a nonzero 2^32 argument. That last argument returns base+2^32 in the nonzero-field-0x58 path, but **the data base itself** in the mask-65535 path. Thus “masked offset zero” and “raw argument zero” have distinct results. Legal VM argument widths, field identities, allocation bounds, active-VM lifetime and malformed-pointer dereference behavior remain open.
|
| 35 |
+
|
| 36 |
+
## NAT-003: trace, PVS and area-query structure
|
| 37 |
+
|
| 38 |
+
SV_Trace substitutes a shared vector for NULL mins/maxs through conditional moves. The vector lies in **.bss**, not file-backed data; its twelve bytes have a loader zero-fill initial value. The report marks that origin explicitly rather than claiming a file read or verified unchanged runtime contents. The graph calls **CM_BoxTrace** before the possible **SV_ClipMoveToEntities** path. File-backed constants **1.0/-1.0** and native swept-bound instructions are retained. The complete collision algorithm and exceptional float branches are not evaluated.
|
| 39 |
+
|
| 40 |
+
The trace return path copies **seven eight-byte chunks**, output offsets 0/8/16/24/32/40/48, from its local collision result to the caller. That establishes an observed **56-byte copy span**, not every member's type or a portable C-layout assertion. In particular, the crosshair word at result +4 and endpoint reads +12/+16/+20 still need semantic field corroboration before naming them as final Rust types.
|
| 41 |
+
|
| 42 |
+
SV_inPVS obtains both point leaf numbers, clusters and areas. It asks **CM_ClusterPVS** for the first point's cluster mask. With a non-NULL mask, it tests the second cluster's byte/bit using signed index shift by 3 and low bits masked by 7; a clear visibility bit returns false. A NULL mask bypasses that bit restriction. The remaining path calls **CM_AreasConnected** and normalizes nonzero to true. This is cluster/area connectivity evidence, not an unobstructed ray test. Cluster bounds, NULL-mask production, portals and real map fixtures remain open.
|
| 43 |
+
|
| 44 |
+
SV_AreaEntities initializes a stack query record: mins/maxs pointers, output-list pointer, count zero and maximum count. It calls **SV_AreaEntities_r** with the native spatial-tree root, then returns the count. The recursive graph visits linked entities, gets their game objects through SV_GEntityForSvEntity, and checks raw coordinate fields **0x1d0 through 0x1e4** against query bounds. Strict greater/less comparisons imply touching finite bounds are not rejected by those six checks; NaNs are not characterized here.
|
| 45 |
+
|
| 46 |
+
The capacity test is **count == maximum**, not a recovered >= guard. At equality, the graph tail requests Com_Printf with file-backed **`SV_AreaEntities: MAXCOUNT\n`**. Otherwise it writes an index at `output + count*4` and increments count. This confirms four-byte index elements for the QVM location query, whose supplied maximum is 1024. Exact index derivation, tree ordering, node-boundary recursion, malformed count/maximum inputs, link ownership and clipping remain open; no query fixture is executed against original map geometry.
|
| 47 |
+
|
| 48 |
+
## Remaining work and Rust dependencies
|
| 49 |
+
|
| 50 |
+
RE-285–287 record shipped destination/transport, bounded VM-pointer and native spatial-graph milestones. RE-284 remains open for runtime/layout/platform completeness; RE-288 tracks all-platform dispatch comparison, libm/float exception conformance, active-VM allocation/mask invariants, full trace fields and collision internals, PVS/portal/tree/index ordering and original map/runtime fixtures. Rust can now distinguish sine/cosine float-bit services and point/box/visibility interfaces with direct Linux evidence, while full collision parity and cross-platform behavior remain explicit dependencies.
|
docs/research/README.md
CHANGED
|
@@ -41,10 +41,11 @@ python3 scripts/test_chat_expansion.py
|
|
| 41 |
python3 scripts/test_chat_items_time.py
|
| 42 |
python3 scripts/test_chat_locations.py
|
| 43 |
python3 scripts/test_chat_crosshair.py
|
|
|
|
| 44 |
python3 scripts/storage_policy.py check --require-setup
|
| 45 |
```
|
| 46 |
|
| 47 |
-
The pipeline runs `fetch_analysis_references.py`, `analyze_qvm.py`, `analyze_native.py`, `analyze_vm_abi.py`, `analyze_native_dispatch.py`, `analyze_vm_extensions.py`, `analyze_native_metadata.py`, `analyze_native_coverage.py`, `analyze_auth_drop.py`, `analyze_deferred_auth.py`, `analyze_engine_control.py`, `analyze_frame_timing.py`, `analyze_event_queues.py`, `analyze_auth_announcements.py`, `analyze_game_cvars.py`, `analyze_cvar_changes.py`, `analyze_auth_queries.py`, `analyze_selector_bounds.py`, `analyze_chat_paths.py`, `analyze_chat_delivery.py`, `analyze_chat_expansion.py`, `analyze_chat_items_time.py`, `analyze_chat_locations.py`, and `
|
| 48 |
|
| 49 |
Generated JSON/JSONL and compressed evidence are regenerated in place; keep prose notes in Markdown. Rerunning the four analysis stages reproduced every generated report and gzip artifact byte-for-byte on the same toolchain. gzip timestamps and stored filenames are fixed. Different objdump versions can produce different disassembly text, so tool version and uncompressed evidence hashes are recorded. Reports are UTF-8 normal Git text, with individual files below the storage policy's 2 MiB limit.
|
| 50 |
|
|
@@ -94,3 +95,5 @@ The extension collector adds five focused tests for native tail calls, command-r
|
|
| 94 |
[Team-leader and location lookup paths](CHAT_LOCATIONS.md) adds RE-277–279: first-match leader scan, strict cache/format boundaries, location registration/list order and retained spatial control flow/constants. Reproduce with `python3 scripts/analyze_chat_locations.py`; check with `python3 scripts/test_chat_locations.py`. Geometry/services, ownership, caller output and runtime/platform contracts remain open.
|
| 95 |
|
| 96 |
[Crosshair substitution geometry and results](CHAT_CROSSHAIR.md) adds RE-281–283: bounded origin/basis/endpoint arithmetic, exact trace arguments and status/temp-object/fallback routes. Reproduce with `python3 scripts/analyze_chat_crosshair.py`; check with `python3 scripts/test_chat_crosshair.py`. Engine trig/collision and complete output/runtime/platform conformance remain open.
|
|
|
|
|
|
|
|
|
| 41 |
python3 scripts/test_chat_items_time.py
|
| 42 |
python3 scripts/test_chat_locations.py
|
| 43 |
python3 scripts/test_chat_crosshair.py
|
| 44 |
+
python3 scripts/test_native_spatial.py
|
| 45 |
python3 scripts/storage_policy.py check --require-setup
|
| 46 |
```
|
| 47 |
|
| 48 |
+
The pipeline runs `fetch_analysis_references.py`, `analyze_qvm.py`, `analyze_native.py`, `analyze_vm_abi.py`, `analyze_native_dispatch.py`, `analyze_vm_extensions.py`, `analyze_native_metadata.py`, `analyze_native_coverage.py`, `analyze_auth_drop.py`, `analyze_deferred_auth.py`, `analyze_engine_control.py`, `analyze_frame_timing.py`, `analyze_event_queues.py`, `analyze_auth_announcements.py`, `analyze_game_cvars.py`, `analyze_cvar_changes.py`, `analyze_auth_queries.py`, `analyze_selector_bounds.py`, `analyze_chat_paths.py`, `analyze_chat_delivery.py`, `analyze_chat_expansion.py`, `analyze_chat_items_time.py`, `analyze_chat_locations.py`, `analyze_chat_crosshair.py`, and `analyze_native_spatial.py` in that order. Python 3.9+ and **LLVM objdump** with x86 ELF/COFF/Mach-O support are required. This pass used Apple LLVM 17.0.0 on macOS arm64; it disassembled x86 images without running them. Upstream references are downloaded only if absent, checked against the committed SHA-256 manifest, and cached under `.cache/research/upstream/`. A clone also needs `git lfs pull` to obtain the derived artifacts/extracted members.
|
| 49 |
|
| 50 |
Generated JSON/JSONL and compressed evidence are regenerated in place; keep prose notes in Markdown. Rerunning the four analysis stages reproduced every generated report and gzip artifact byte-for-byte on the same toolchain. gzip timestamps and stored filenames are fixed. Different objdump versions can produce different disassembly text, so tool version and uncompressed evidence hashes are recorded. Reports are UTF-8 normal Git text, with individual files below the storage policy's 2 MiB limit.
|
| 51 |
|
|
|
|
| 95 |
[Team-leader and location lookup paths](CHAT_LOCATIONS.md) adds RE-277–279: first-match leader scan, strict cache/format boundaries, location registration/list order and retained spatial control flow/constants. Reproduce with `python3 scripts/analyze_chat_locations.py`; check with `python3 scripts/test_chat_locations.py`. Geometry/services, ownership, caller output and runtime/platform contracts remain open.
|
| 96 |
|
| 97 |
[Crosshair substitution geometry and results](CHAT_CROSSHAIR.md) adds RE-281–283: bounded origin/basis/endpoint arithmetic, exact trace arguments and status/temp-object/fallback routes. Reproduce with `python3 scripts/analyze_chat_crosshair.py`; check with `python3 scripts/test_chat_crosshair.py`. Engine trig/collision and complete output/runtime/platform conformance remain open.
|
| 98 |
+
|
| 99 |
+
[Native trig, spatial services and VM pointers](NATIVE_SPATIAL.md) adds RE-285–287: confirmed paired Linux service mappings/float transport, bounded VM_ArgPtr branches and native trace/PVS/area-query graphs. Reproduce with `python3 scripts/analyze_native_spatial.py`; check with `python3 scripts/test_native_spatial.py`. Complete geometry, layout, exceptional arithmetic and all-platform runtime contracts remain open.
|
docs/research/native-spatial.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
scripts/analyze_binaries.py
CHANGED
|
@@ -14,7 +14,7 @@ def main():
|
|
| 14 |
'analyze_deferred_auth.py', 'analyze_engine_control.py', 'analyze_frame_timing.py',
|
| 15 |
'analyze_event_queues.py', 'analyze_auth_announcements.py', 'analyze_game_cvars.py',
|
| 16 |
'analyze_cvar_changes.py', 'analyze_auth_queries.py', 'analyze_selector_bounds.py',
|
| 17 |
-
'analyze_chat_paths.py', 'analyze_chat_delivery.py', 'analyze_chat_expansion.py', 'analyze_chat_items_time.py', 'analyze_chat_locations.py', 'analyze_chat_crosshair.py'):
|
| 18 |
subprocess.run([sys.executable, str(Path('scripts')/script)], check=True)
|
| 19 |
|
| 20 |
|
|
|
|
| 14 |
'analyze_deferred_auth.py', 'analyze_engine_control.py', 'analyze_frame_timing.py',
|
| 15 |
'analyze_event_queues.py', 'analyze_auth_announcements.py', 'analyze_game_cvars.py',
|
| 16 |
'analyze_cvar_changes.py', 'analyze_auth_queries.py', 'analyze_selector_bounds.py',
|
| 17 |
+
'analyze_chat_paths.py', 'analyze_chat_delivery.py', 'analyze_chat_expansion.py', 'analyze_chat_items_time.py', 'analyze_chat_locations.py', 'analyze_chat_crosshair.py', 'analyze_native_spatial.py'):
|
| 18 |
subprocess.run([sys.executable, str(Path('scripts')/script)], check=True)
|
| 19 |
|
| 20 |
|
scripts/analyze_native_spatial.py
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Recover Linux ELF64 spatial/trig dispatch and bounded VM pointer traces."""
|
| 3 |
+
import gzip
|
| 4 |
+
import json
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
import re
|
| 7 |
+
import struct
|
| 8 |
+
from analyze_chat_paths import native_string
|
| 9 |
+
from analyze_deferred_auth import signed32
|
| 10 |
+
from analyze_engine_control import control_flow
|
| 11 |
+
from analyze_frame_timing import read_address
|
| 12 |
+
from analyze_native import elf
|
| 13 |
+
from analyze_native_dispatch import recover
|
| 14 |
+
from analyze_qvm import write_json
|
| 15 |
+
from analyze_vm_extensions import native_functions,verified
|
| 16 |
+
|
| 17 |
+
MASK64=2**64-1
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def case_path(graph,address,limit=128):
|
| 21 |
+
index=next((i for i,x in enumerate(graph['instructions']) if x['address']==address),None)
|
| 22 |
+
if index is None:raise ValueError('case address missing')
|
| 23 |
+
rows=[]
|
| 24 |
+
for x in graph['instructions'][index:index+limit]:
|
| 25 |
+
rows.append(x)
|
| 26 |
+
if x['opcode'] in ['jmp','jmpq','ret','retq']:return rows
|
| 27 |
+
if x['opcode'].startswith('j'):raise ValueError('branching case needs a full CFG')
|
| 28 |
+
raise ValueError('case lacks bounded terminal transfer')
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def pointer_trace(graph,argument,current_vm,flag,data_base,data_mask,limit=64):
|
| 32 |
+
"""Evaluate only the observed VM_ArgPtr integer instructions with synthetic words."""
|
| 33 |
+
instructions={x['address']:x for x in graph['instructions']}
|
| 34 |
+
order={x['address']:i for i,x in enumerate(graph['instructions'])};rows=graph['instructions']
|
| 35 |
+
regs={'%rdi':argument&MASK64};m={current_vm+0x58:flag,current_vm+0x90:data_base,
|
| 36 |
+
current_vm+0x98:data_mask};zero=False;trace=[];pc=graph['entry']
|
| 37 |
+
def reg(r):
|
| 38 |
+
if r not in regs:raise ValueError('unknown pointer register')
|
| 39 |
+
return regs[r]
|
| 40 |
+
def read(address):
|
| 41 |
+
if address not in m:raise ValueError('unknown pointer word')
|
| 42 |
+
return m[address]
|
| 43 |
+
for _ in range(limit):
|
| 44 |
+
if pc not in instructions:raise ValueError('pointer trace escaped function')
|
| 45 |
+
x=instructions[pc];trace.append(pc);op=x['opcode'];args=x['operands'].split('#')[0].strip()
|
| 46 |
+
nextpc=rows[order[pc]+1]['address'] if order[pc]+1<len(rows) else None
|
| 47 |
+
if op=='testq':
|
| 48 |
+
a,b=args.split(', ');zero=(reg(a)®(b))==0
|
| 49 |
+
elif op=='xorl' and args=='%eax, %eax':regs['%rax']=0
|
| 50 |
+
elif op in ['je','jne']:
|
| 51 |
+
if zero==(op=='je'):nextpc=int(args.split()[0],16)
|
| 52 |
+
elif op=='cmpq' and args=='$0x0, 0x58(%rdx)':zero=read(reg('%rdx')+0x58)==0
|
| 53 |
+
elif op=='movq' and '(%rip), %rdx' in args:
|
| 54 |
+
if '<currentVM>' not in x['operands']:raise ValueError('pointer global identity changed')
|
| 55 |
+
regs['%rdx']=current_vm
|
| 56 |
+
elif op=='movq' and args=='%rdi, %rax':regs['%rax']=reg('%rdi')
|
| 57 |
+
elif op=='movslq' and args=='0x98(%rdx), %rax':regs['%rax']=signed32(read(reg('%rdx')+0x98))&MASK64
|
| 58 |
+
elif op=='andq' and args=='%rdi, %rax':regs['%rax']=reg('%rax')®('%rdi')
|
| 59 |
+
elif op=='addq' and args=='0x90(%rdx), %rax':regs['%rax']=(reg('%rax')+read(reg('%rdx')+0x90))&MASK64
|
| 60 |
+
elif op in ['ret','retq']:return {'trace':trace,'result':reg('%rax')}
|
| 61 |
+
else:raise ValueError('unsupported pointer instruction '+op+' '+args)
|
| 62 |
+
pc=nextpc
|
| 63 |
+
raise ValueError('pointer trace step limit')
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def main():
|
| 67 |
+
out={'native':{},'limitations':'Static Linux ELF64 dispatch/graphs and bounded synthetic VM_ArgPtr '
|
| 68 |
+
'instruction traces. No original process/native callee/collision/trig service executes. Pointer '
|
| 69 |
+
'fixtures supply currentVM fields; allocation/mask invariants, malformed pointers, exceptional '
|
| 70 |
+
'floats, geometry/portal behavior and other platforms remain open.'}
|
| 71 |
+
for label in ['linux--Quake3-UrT-Ded.x86_64','linux--Quake3-UrT.x86_64']:
|
| 72 |
+
r=json.loads(Path(f'docs/research/native/{label}.json').read_text())
|
| 73 |
+
data=verified((Path('.cache/UrbanTerror43')/r['source']['path']).read_bytes(),r['source']['sha256'])
|
| 74 |
+
a=r['artifacts']['disassembly.txt'];text=verified(gzip.open(a['path'],'rb').read(),a['uncompressed_sha256']).decode()
|
| 75 |
+
metadata,_=elf(data);fs=native_functions(text);dispatch=recover(data,text,'SV_GameSystemCalls')
|
| 76 |
+
graph=control_flow(fs['SV_GameSystemCalls']);cases={}
|
| 77 |
+
for n in [24,26,32,103,104]:
|
| 78 |
+
case=next(c for c in dispatch['cases'] if n in c['numbers_sharing_target'])
|
| 79 |
+
path=case_path(graph,case['target_address'])
|
| 80 |
+
calls=[x for x in path if x['opcode'].startswith('call')]
|
| 81 |
+
cases[str(n)]={'target_address':case['target_address'],'instructions':path,'calls':calls}
|
| 82 |
+
names=['VM_ArgPtr','SV_Trace','SV_inPVS','SV_AreaEntities','SV_AreaEntities_r','SV_ClipMoveToEntities']
|
| 83 |
+
graphs={n:control_flow(fs[n]) for n in names}
|
| 84 |
+
zero_ins=next(x for x in graphs['SV_Trace']['instructions'] if re.match(r'\$0x[0-9a-f]+, %esi',x['operands']))
|
| 85 |
+
zero_address=int(re.search(r'\$0x([0-9a-f]+)',zero_ins['operands'])[1],16)
|
| 86 |
+
sections=[s for s in metadata['sections'] if s['address']<=zero_address and zero_address+12<=s['address']+s['bytes']]
|
| 87 |
+
if len(sections)!=1:raise ValueError('ambiguous extent section')
|
| 88 |
+
section=sections[0]
|
| 89 |
+
if section['zero_fill']:raw,offset=bytes(12),None
|
| 90 |
+
else:raw,offset=read_address(data,metadata['sections'],zero_address,12)
|
| 91 |
+
constants=[]
|
| 92 |
+
for x in graphs['SV_Trace']['instructions']:
|
| 93 |
+
if x['opcode']=='movss' and '(%rip)' in x['operands']:
|
| 94 |
+
address=int(re.search(r'#\s*0x([0-9a-f]+)',x['operands'])[1],16)
|
| 95 |
+
value,fileoff=read_address(data,metadata['sections'],address,4)
|
| 96 |
+
constants.append({'instruction':x['address'],'address':address,'file_offset':fileoff,
|
| 97 |
+
'bits':struct.unpack('<I',value)[0],'float32':struct.unpack('<f',value)[0]})
|
| 98 |
+
warning_ins=next(x for x in reversed(graphs['SV_AreaEntities_r']['instructions'])
|
| 99 |
+
if x['opcode']=='movl' and re.match(r'\$0x[0-9a-f]+, %edi',x['operands']))
|
| 100 |
+
warning_address=int(re.search(r'\$0x([0-9a-f]+)',warning_ins['operands'])[1],16)
|
| 101 |
+
warning={'address':warning_address,'text':native_string(data,metadata['sections'],warning_address)}
|
| 102 |
+
traces=[]
|
| 103 |
+
for argument,vm,flag,mask in [(0,0,0,65535),(1,0,0,65535),(256,0x20000,1,65535),
|
| 104 |
+
(0x1234,0x20000,0,255),(511,0x20000,0,255),(-1,0x20000,0,65535),
|
| 105 |
+
(0x1234,0x20000,0,-1),(2**32,0x20000,1,65535),(2**32,0x20000,0,65535)]:
|
| 106 |
+
t=pointer_trace(graphs['VM_ArgPtr'],argument,vm,flag,0x100000,mask)
|
| 107 |
+
traces.append({'argument':argument,'current_vm':vm,'field58':flag,'data_base':0x100000,
|
| 108 |
+
'mask_field98':mask,'trace':t})
|
| 109 |
+
out['native'][label]={'source':r['source'],'disassembly_sha256':a['uncompressed_sha256'],
|
| 110 |
+
'dispatch_table_address':dispatch['table_address'],'cases':cases,'graphs':graphs,
|
| 111 |
+
'zero_extent':{'address':zero_address,'file_offset':offset,'section':section['name'],
|
| 112 |
+
'zero_fill_initial_value':section['zero_fill'],'raw':raw.hex(),
|
| 113 |
+
'float32':list(struct.unpack('<3f',raw))},'trace_float_constants':constants,
|
| 114 |
+
'pointer_traces':traces,'area_capacity_warning':warning}
|
| 115 |
+
write_json(Path('docs/research/native-spatial.json'),out)
|
| 116 |
+
print('Recovered paired Linux trig/spatial dispatch and 18 bounded VM pointer paths')
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
if __name__=='__main__':main()
|
scripts/test_native_spatial.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Check paired dispatch evidence and fail-closed native pointer evaluation."""
|
| 3 |
+
import copy
|
| 4 |
+
import json
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
import unittest
|
| 7 |
+
from analyze_native_spatial import case_path,pointer_trace
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class NativeSpatialTests(unittest.TestCase):
|
| 11 |
+
@classmethod
|
| 12 |
+
def setUpClass(cls):cls.r=json.loads(Path('docs/research/native-spatial.json').read_text())
|
| 13 |
+
|
| 14 |
+
def test_trig_cases_float_input_and_bit_return(self):
|
| 15 |
+
for n in self.r['native'].values():
|
| 16 |
+
for number,name in [('103','sinf@plt'),('104','cosf@plt')]:
|
| 17 |
+
c=n['cases'][number];lines='\n'.join(x['line'] for x in c['instructions'])
|
| 18 |
+
self.assertIn('<'+name+'>',lines)
|
| 19 |
+
self.assertIn('movss\t0x8(%rdi), %xmm0',lines)
|
| 20 |
+
self.assertIn('movss\t%xmm0, 0x3c(%rsp)',lines)
|
| 21 |
+
self.assertIn('cltq',lines)
|
| 22 |
+
self.assertEqual(len(c['calls']),1)
|
| 23 |
+
|
| 24 |
+
def test_spatial_dispatch_complete_conversion_counts(self):
|
| 25 |
+
for n in self.r['native'].values():
|
| 26 |
+
for number,target,count in [('24','SV_Trace',5),('26','SV_inPVS',2),('32','SV_AreaEntities',3)]:
|
| 27 |
+
calls=n['cases'][number]['calls'];lines='\n'.join(x['line'] for x in calls)
|
| 28 |
+
self.assertEqual(lines.count('<VM_ArgPtr>'),count)
|
| 29 |
+
self.assertIn('<'+target+'>',calls[-1]['line'])
|
| 30 |
+
lines='\n'.join(x['line'] for x in n['cases']['24']['instructions'])
|
| 31 |
+
self.assertIn('movl\t$0x0, 0x8(%rsp)',lines)
|
| 32 |
+
self.assertIn('movl\t%eax, (%rsp)',lines)
|
| 33 |
+
|
| 34 |
+
def test_pointer_null_direct_mask_and_large_argument(self):
|
| 35 |
+
expected=[0,0,0x100100,0x100034,0x1000ff,0x10ffff,0x101234,0x100100000,0x100000]
|
| 36 |
+
for n in self.r['native'].values():
|
| 37 |
+
self.assertEqual([x['trace']['result'] for x in n['pointer_traces']],expected)
|
| 38 |
+
graph=n['graphs']['VM_ArgPtr']
|
| 39 |
+
for x in n['pointer_traces']:
|
| 40 |
+
result=pointer_trace(graph,x['argument'],x['current_vm'],x['field58'],x['data_base'],x['mask_field98'])
|
| 41 |
+
self.assertEqual(result,x['trace'])
|
| 42 |
+
self.assertNotEqual(n['pointer_traces'][-1]['trace']['result'],0)
|
| 43 |
+
|
| 44 |
+
def test_pointer_rejects_unsupported_instructions_and_limits(self):
|
| 45 |
+
for n in self.r['native'].values():
|
| 46 |
+
graph=n['graphs']['VM_ArgPtr']
|
| 47 |
+
with self.assertRaises(ValueError):pointer_trace(graph,256,0x20000,0,0x100000,255,limit=1)
|
| 48 |
+
bad=copy.deepcopy(graph);bad['instructions'][0]['opcode']='nop'
|
| 49 |
+
with self.assertRaises(ValueError):pointer_trace(bad,1,0,0,0,0)
|
| 50 |
+
|
| 51 |
+
def test_case_collector_rejects_unbounded_branching_or_missing(self):
|
| 52 |
+
graph={'instructions':[{'address':1,'opcode':'movq'},{'address':2,'opcode':'jmp'}]}
|
| 53 |
+
self.assertEqual(len(case_path(graph,1)),2)
|
| 54 |
+
with self.assertRaises(ValueError):case_path(graph,3)
|
| 55 |
+
with self.assertRaises(ValueError):case_path(graph,1,limit=1)
|
| 56 |
+
with self.assertRaises(ValueError):case_path({'instructions':[{'address':1,'opcode':'je'}]},1)
|
| 57 |
+
|
| 58 |
+
def test_null_extents_and_trace_result_copy(self):
|
| 59 |
+
for n in self.r['native'].values():
|
| 60 |
+
extent=n['zero_extent'];self.assertEqual(extent['float32'],[0,0,0])
|
| 61 |
+
self.assertTrue(extent['zero_fill_initial_value']);self.assertIsNone(extent['file_offset'])
|
| 62 |
+
self.assertEqual({x['float32'] for x in n['trace_float_constants']},{-1.0,1.0})
|
| 63 |
+
lines='\n'.join(x['line'] for x in n['graphs']['SV_Trace']['instructions'])
|
| 64 |
+
for marker in ['cmovneq\t%rdx, %r12','cmovneq\t%rcx, %r13','<CM_BoxTrace>',
|
| 65 |
+
'<SV_ClipMoveToEntities>','0x30(%rbp)']:
|
| 66 |
+
self.assertIn(marker,lines)
|
| 67 |
+
|
| 68 |
+
def test_pvs_and_area_search_static_gates(self):
|
| 69 |
+
for n in self.r['native'].values():
|
| 70 |
+
p=n['graphs']['SV_inPVS'];labels=[c['label'] for c in p['calls']]
|
| 71 |
+
self.assertEqual(labels,['CM_PointLeafnum','CM_LeafCluster','CM_LeafArea','CM_ClusterPVS',
|
| 72 |
+
'CM_PointLeafnum','CM_LeafCluster','CM_LeafArea','CM_AreasConnected'])
|
| 73 |
+
lines='\n'.join(x['line'] for x in p['instructions'])
|
| 74 |
+
for marker in ['$0x7','$0x3','testb\t$0x1','setne\t%dl']:self.assertIn(marker,lines)
|
| 75 |
+
self.assertEqual(n['area_capacity_warning']['text'],'SV_AreaEntities: MAXCOUNT\n')
|
| 76 |
+
area='\n'.join(x['line'] for x in n['graphs']['SV_AreaEntities_r']['instructions'])
|
| 77 |
+
for marker in ['0x1d0(%rax)','0x1e4(%rax)','cmpl\t0x1c(%rbp), %eax',
|
| 78 |
+
'(%rax,%rdx,4)','<Com_Printf>']:self.assertIn(marker,area)
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
if __name__=='__main__':unittest.main()
|