nmarshall commited on
Commit
9c0f602
·
1 Parent(s): 3ed15e9

qvm: expose explicit child byte effects

Browse files
docs/FINDINGS.md CHANGED
@@ -1406,3 +1406,6 @@ RE-791–800 adds exact Rust source-sort/ranking parity, mixed count/prefix sema
1406
 
1407
 
1408
  **RE-802:** Bounded tracing can now preserve byte/word coherence and execute unaligned byte copies without changing legacy observations. [Evidence](research/QVM_COHERENT_MEMORY.md).
 
 
 
 
1406
 
1407
 
1408
  **RE-802:** Bounded tracing can now preserve byte/word coherence and execute unaligned byte copies without changing legacy observations. [Evidence](research/QVM_COHERENT_MEMORY.md).
1409
+
1410
+
1411
+ **RE-803:** Both bounded resumers now support validated child byte writes, coherent word mirroring and explicit word/byte/return precedence. [Evidence](research/QVM_CHILD_BYTE_EFFECTS.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -1413,3 +1413,6 @@ RE-791–800 validation: 1,562 Python and102 Rust tests pass;226 affected produc
1413
 
1414
 
1415
  RE-802: Bounded tracing can now preserve byte/word coherence and execute unaligned byte copies without changing legacy observations. Full runtime completion remains open. [Evidence](research/QVM_COHERENT_MEMORY.md).
 
 
 
 
1413
 
1414
 
1415
  RE-802: Bounded tracing can now preserve byte/word coherence and execute unaligned byte copies without changing legacy observations. Full runtime completion remains open. [Evidence](research/QVM_COHERENT_MEMORY.md).
1416
+
1417
+
1418
+ RE-803: Both bounded resumers now support validated child byte writes, coherent word mirroring and explicit word/byte/return precedence. Full runtime completion remains open. [Evidence](research/QVM_CHILD_BYTE_EFFECTS.md).
docs/RESEARCH_LEDGER.md CHANGED
@@ -1676,3 +1676,8 @@ After exactly ten task commits from `c6b4a1eb`, the single `cargo xtask test-ful
1676
  ## 2026-10-26 — RE-802 Opt-in coherent byte and unaligned word research memory
1677
 
1678
  Bounded tracing can now preserve byte/word coherence and execute unaligned byte copies without changing legacy observations. Focused `cargo xtask test-group coherent-memory` passes (6 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
 
 
 
 
 
 
1676
  ## 2026-10-26 — RE-802 Opt-in coherent byte and unaligned word research memory
1677
 
1678
  Bounded tracing can now preserve byte/word coherence and execute unaligned byte copies without changing legacy observations. Focused `cargo xtask test-group coherent-memory` passes (6 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
1679
+
1680
+
1681
+ ## 2026-10-26 — RE-803 Explicit child byte effects and read-only shared byte views
1682
+
1683
+ Both bounded resumers now support validated child byte writes, coherent word mirroring and explicit word/byte/return precedence. Focused `cargo xtask test-group child-byte-effects` passes (6 Python tests); selected reports regenerate twice deterministically, with storage, documentation links and whitespace guards. Full suite deferred to task ten. Original assets unchanged; source fixtures do not establish complete native/runtime parity.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -1456,3 +1456,6 @@ Purpose: turn the supplied installation into an evidence-backed specification of
1456
 
1457
 
1458
  - [x] RE-802 Opt-in coherent byte and unaligned word research memory ([evidence](research/QVM_COHERENT_MEMORY.md)).
 
 
 
 
1456
 
1457
 
1458
  - [x] RE-802 Opt-in coherent byte and unaligned word research memory ([evidence](research/QVM_COHERENT_MEMORY.md)).
1459
+
1460
+
1461
+ - [x] RE-803 Explicit child byte effects and read-only shared byte views ([evidence](research/QVM_CHILD_BYTE_EFFECTS.md)).
docs/research/QVM_CHILD_BYTE_EFFECTS.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Explicit child byte effects and read-only shared byte views
2
+
3
+ RE-803. Reproduce with `python3 scripts/analyze_qvm_child_byte_effects.py`; focused validation: `cargo xtask test-group child-byte-effects`. [Machine report](qvm-child-byte-effects.json).
4
+
5
+ Forty independent byte-lane probes verify child word writes followed by explicit byte overrides across trace and movement resumers. Children receive a read-only byte view and return child_memory_bytes effects; capture of final byte state is opt-in. Movement command tuples retain precedence at the next segment. Unsupported modes reject. Legacy handlers and defaults retain their signatures and behavior.
6
+
7
+ Original executable/native runtime and complete Linux/macOS Rust/Bevy/Solari acceptance remain unverified.
docs/research/README.md CHANGED
@@ -996,3 +996,6 @@ The extension collector adds five focused tests for native tail calls, command-r
996
 
997
 
998
  [RE-802: Opt-in coherent byte and unaligned word research memory](QVM_COHERENT_MEMORY.md).
 
 
 
 
996
 
997
 
998
  [RE-802: Opt-in coherent byte and unaligned word research memory](QVM_COHERENT_MEMORY.md).
999
+
1000
+
1001
+ [RE-803: Explicit child byte effects and read-only shared byte views](QVM_CHILD_BYTE_EFFECTS.md).
docs/research/qvm-child-byte-effects.json ADDED
@@ -0,0 +1,325 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "limits": "Explicit opt-in read-only child byte view plus validated child_memory_bytes effects. Changed words apply before byte overrides; returned CALL value patch follows both. Movement command tuple remains authoritative at the next segment. No complete native VM/ABI claim.",
3
+ "probes": [
4
+ {
5
+ "byte": 0,
6
+ "kind": "trace",
7
+ "lane": 0,
8
+ "locked": true,
9
+ "result": 1432778496,
10
+ "stored": 1432778496
11
+ },
12
+ {
13
+ "byte": 1,
14
+ "kind": "trace",
15
+ "lane": 0,
16
+ "locked": true,
17
+ "result": 1432778497,
18
+ "stored": 1432778497
19
+ },
20
+ {
21
+ "byte": 127,
22
+ "kind": "trace",
23
+ "lane": 0,
24
+ "locked": true,
25
+ "result": 1432778623,
26
+ "stored": 1432778623
27
+ },
28
+ {
29
+ "byte": 128,
30
+ "kind": "trace",
31
+ "lane": 0,
32
+ "locked": true,
33
+ "result": 1432778624,
34
+ "stored": 1432778624
35
+ },
36
+ {
37
+ "byte": 255,
38
+ "kind": "trace",
39
+ "lane": 0,
40
+ "locked": true,
41
+ "result": 1432778751,
42
+ "stored": 1432778751
43
+ },
44
+ {
45
+ "byte": 0,
46
+ "kind": "trace",
47
+ "lane": 1,
48
+ "locked": true,
49
+ "result": 1432748168,
50
+ "stored": 1432748168
51
+ },
52
+ {
53
+ "byte": 1,
54
+ "kind": "trace",
55
+ "lane": 1,
56
+ "locked": true,
57
+ "result": 1432748424,
58
+ "stored": 1432748424
59
+ },
60
+ {
61
+ "byte": 127,
62
+ "kind": "trace",
63
+ "lane": 1,
64
+ "locked": true,
65
+ "result": 1432780680,
66
+ "stored": 1432780680
67
+ },
68
+ {
69
+ "byte": 128,
70
+ "kind": "trace",
71
+ "lane": 1,
72
+ "locked": true,
73
+ "result": 1432780936,
74
+ "stored": 1432780936
75
+ },
76
+ {
77
+ "byte": 255,
78
+ "kind": "trace",
79
+ "lane": 1,
80
+ "locked": true,
81
+ "result": 1432813448,
82
+ "stored": 1432813448
83
+ },
84
+ {
85
+ "byte": 0,
86
+ "kind": "trace",
87
+ "lane": 2,
88
+ "locked": true,
89
+ "result": 1426093960,
90
+ "stored": 1426093960
91
+ },
92
+ {
93
+ "byte": 1,
94
+ "kind": "trace",
95
+ "lane": 2,
96
+ "locked": true,
97
+ "result": 1426159496,
98
+ "stored": 1426159496
99
+ },
100
+ {
101
+ "byte": 127,
102
+ "kind": "trace",
103
+ "lane": 2,
104
+ "locked": true,
105
+ "result": 1434417032,
106
+ "stored": 1434417032
107
+ },
108
+ {
109
+ "byte": 128,
110
+ "kind": "trace",
111
+ "lane": 2,
112
+ "locked": true,
113
+ "result": 1434482568,
114
+ "stored": 1434482568
115
+ },
116
+ {
117
+ "byte": 255,
118
+ "kind": "trace",
119
+ "lane": 2,
120
+ "locked": true,
121
+ "result": 1442805640,
122
+ "stored": 1442805640
123
+ },
124
+ {
125
+ "byte": 0,
126
+ "kind": "trace",
127
+ "lane": 3,
128
+ "locked": true,
129
+ "result": 6715272,
130
+ "stored": 6715272
131
+ },
132
+ {
133
+ "byte": 1,
134
+ "kind": "trace",
135
+ "lane": 3,
136
+ "locked": true,
137
+ "result": 23492488,
138
+ "stored": 23492488
139
+ },
140
+ {
141
+ "byte": 127,
142
+ "kind": "trace",
143
+ "lane": 3,
144
+ "locked": true,
145
+ "result": 2137421704,
146
+ "stored": 2137421704
147
+ },
148
+ {
149
+ "byte": 128,
150
+ "kind": "trace",
151
+ "lane": 3,
152
+ "locked": true,
153
+ "result": 2154198920,
154
+ "stored": 2154198920
155
+ },
156
+ {
157
+ "byte": 255,
158
+ "kind": "trace",
159
+ "lane": 3,
160
+ "locked": true,
161
+ "result": 4284905352,
162
+ "stored": 4284905352
163
+ },
164
+ {
165
+ "byte": 0,
166
+ "kind": "movement",
167
+ "lane": 0,
168
+ "locked": true,
169
+ "result": 1432778496,
170
+ "stored": 1432778496
171
+ },
172
+ {
173
+ "byte": 1,
174
+ "kind": "movement",
175
+ "lane": 0,
176
+ "locked": true,
177
+ "result": 1432778497,
178
+ "stored": 1432778497
179
+ },
180
+ {
181
+ "byte": 127,
182
+ "kind": "movement",
183
+ "lane": 0,
184
+ "locked": true,
185
+ "result": 1432778623,
186
+ "stored": 1432778623
187
+ },
188
+ {
189
+ "byte": 128,
190
+ "kind": "movement",
191
+ "lane": 0,
192
+ "locked": true,
193
+ "result": 1432778624,
194
+ "stored": 1432778624
195
+ },
196
+ {
197
+ "byte": 255,
198
+ "kind": "movement",
199
+ "lane": 0,
200
+ "locked": true,
201
+ "result": 1432778751,
202
+ "stored": 1432778751
203
+ },
204
+ {
205
+ "byte": 0,
206
+ "kind": "movement",
207
+ "lane": 1,
208
+ "locked": true,
209
+ "result": 1432748168,
210
+ "stored": 1432748168
211
+ },
212
+ {
213
+ "byte": 1,
214
+ "kind": "movement",
215
+ "lane": 1,
216
+ "locked": true,
217
+ "result": 1432748424,
218
+ "stored": 1432748424
219
+ },
220
+ {
221
+ "byte": 127,
222
+ "kind": "movement",
223
+ "lane": 1,
224
+ "locked": true,
225
+ "result": 1432780680,
226
+ "stored": 1432780680
227
+ },
228
+ {
229
+ "byte": 128,
230
+ "kind": "movement",
231
+ "lane": 1,
232
+ "locked": true,
233
+ "result": 1432780936,
234
+ "stored": 1432780936
235
+ },
236
+ {
237
+ "byte": 255,
238
+ "kind": "movement",
239
+ "lane": 1,
240
+ "locked": true,
241
+ "result": 1432813448,
242
+ "stored": 1432813448
243
+ },
244
+ {
245
+ "byte": 0,
246
+ "kind": "movement",
247
+ "lane": 2,
248
+ "locked": true,
249
+ "result": 1426093960,
250
+ "stored": 1426093960
251
+ },
252
+ {
253
+ "byte": 1,
254
+ "kind": "movement",
255
+ "lane": 2,
256
+ "locked": true,
257
+ "result": 1426159496,
258
+ "stored": 1426159496
259
+ },
260
+ {
261
+ "byte": 127,
262
+ "kind": "movement",
263
+ "lane": 2,
264
+ "locked": true,
265
+ "result": 1434417032,
266
+ "stored": 1434417032
267
+ },
268
+ {
269
+ "byte": 128,
270
+ "kind": "movement",
271
+ "lane": 2,
272
+ "locked": true,
273
+ "result": 1434482568,
274
+ "stored": 1434482568
275
+ },
276
+ {
277
+ "byte": 255,
278
+ "kind": "movement",
279
+ "lane": 2,
280
+ "locked": true,
281
+ "result": 1442805640,
282
+ "stored": 1442805640
283
+ },
284
+ {
285
+ "byte": 0,
286
+ "kind": "movement",
287
+ "lane": 3,
288
+ "locked": true,
289
+ "result": 6715272,
290
+ "stored": 6715272
291
+ },
292
+ {
293
+ "byte": 1,
294
+ "kind": "movement",
295
+ "lane": 3,
296
+ "locked": true,
297
+ "result": 23492488,
298
+ "stored": 23492488
299
+ },
300
+ {
301
+ "byte": 127,
302
+ "kind": "movement",
303
+ "lane": 3,
304
+ "locked": true,
305
+ "result": 2137421704,
306
+ "stored": 2137421704
307
+ },
308
+ {
309
+ "byte": 128,
310
+ "kind": "movement",
311
+ "lane": 3,
312
+ "locked": true,
313
+ "result": 2154198920,
314
+ "stored": 2154198920
315
+ },
316
+ {
317
+ "byte": 255,
318
+ "kind": "movement",
319
+ "lane": 3,
320
+ "locked": true,
321
+ "result": 4284905352,
322
+ "stored": 4284905352
323
+ }
324
+ ]
325
+ }
docs/research/qvm-resumer-audit.json CHANGED
@@ -674,6 +674,28 @@
674
  "repeated_calls_opt_in": false,
675
  "repeated_calls_setting": "default_false"
676
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
677
  {
678
  "backward_conditional_branches": [
679
  22261
@@ -9410,10 +9432,10 @@
9410
  }
9411
  },
9412
  "summary": {
9413
- "call_expressions": 186,
9414
- "files": 145,
9415
- "legacy_expressions": 156,
9416
- "nonliteral_ranges": 22,
9417
  "unresolved_mode_expressions": 3
9418
  }
9419
  }
 
674
  "repeated_calls_opt_in": false,
675
  "repeated_calls_setting": "default_false"
676
  },
677
+ {
678
+ "backward_conditional_branches": [],
679
+ "calls": [],
680
+ "explicit_result_offsets": null,
681
+ "helper": "qvm_trace_support.resume",
682
+ "line": 20,
683
+ "literal_range": null,
684
+ "path": "scripts/analyze_qvm_child_byte_effects.py",
685
+ "repeated_calls_opt_in": false,
686
+ "repeated_calls_setting": "default_false"
687
+ },
688
+ {
689
+ "backward_conditional_branches": [],
690
+ "calls": [],
691
+ "explicit_result_offsets": null,
692
+ "helper": "qvm_research_support.execute",
693
+ "line": 23,
694
+ "literal_range": null,
695
+ "path": "scripts/analyze_qvm_child_byte_effects.py",
696
+ "repeated_calls_opt_in": false,
697
+ "repeated_calls_setting": "default_false"
698
+ },
699
  {
700
  "backward_conditional_branches": [
701
  22261
 
9432
  }
9433
  },
9434
  "summary": {
9435
+ "call_expressions": 188,
9436
+ "files": 146,
9437
+ "legacy_expressions": 158,
9438
+ "nonliteral_ranges": 24,
9439
  "unresolved_mode_expressions": 3
9440
  }
9441
  }
scripts/analyze_qvm_child_byte_effects.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from pathlib import Path
3
+ from qvm_trace_support import resume
4
+ from qvm_research_support import execute
5
+ from analyze_qvm_reentry_witness import instructions,BASE
6
+ from analyze_qvm import write_json
7
+
8
+ def main():
9
+ rows=[]
10
+ for kind in ['trace','movement']:
11
+ for lane in range(4):
12
+ for value in [0,1,127,128,255]:
13
+ ins=instructions([('CONST',99),('CALL',None),('POP',None),('CONST',BASE+64),('LOAD4',None),('LEAVE',0)])
14
+ def child(i,m,a,b):
15
+ locked=False
16
+ try:b[0]=7
17
+ except TypeError:locked=True
18
+ m[BASE+64]=0x55667788;return m,0,{'read_only_view':locked,'child_memory_bytes':{BASE+64+lane:value}}
19
+ opts=dict(repeated_calls=True,sync_child_words=True,coherent_memory=True,byte_handlers=True,capture_byte_memory=True)
20
+ if kind=='trace':m,e=resume(ins,0,len(ins),{BASE+64:0x11223344},BASE,handlers={99:child},**opts)
21
+ else:
22
+ def move(i,m,a,c,b):m,v,r=child(i,m,a,b);return m,c,v,r
23
+ m,c,e=execute(ins,0,len(ins),{BASE+64:0x11223344},[0,0,0],BASE,{99:move},**opts)
24
+ rows.append({'kind':kind,'lane':lane,'byte':value,'result':e['return']&0xffffffff,'stored':m[BASE+64]&0xffffffff,'locked':e['children'][0]['effect']['read_only_view']})
25
+ write_json(Path('docs/research/qvm-child-byte-effects.json'),{'probes':rows,'limits':'Explicit opt-in read-only child byte view plus validated child_memory_bytes effects. Changed words apply before byte overrides; returned CALL value patch follows both. Movement command tuple remains authoritative at the next segment. No complete native VM/ABI claim.'})
26
+ if __name__=='__main__':main()
scripts/qvm_research_support.py CHANGED
@@ -19,8 +19,11 @@ def memory(raw,h,cmd=(100,0,0),plane=1,flags=0):
19
  m[0x30000+24]=sum((v&255)<<(8*(i+1)) for i,v in enumerate(cmd));return m
20
 
21
 
22
- def execute(ins,start,stop,m,cmd,base,handlers=None,result_offsets=None,boundaries=(),byte_inputs=None,repeated_calls=False,sync_child_words=False):
23
  """Bounded source calls with actual recovered children at empty-stack boundaries."""
 
 
 
24
  from qvm_child_memory_support import sync_words
25
  if sync_child_words and not repeated_calls:raise ValueError('child synchronization requires corrected reentry')
26
  import math
@@ -29,10 +32,13 @@ def execute(ins,start,stop,m,cmd,base,handlers=None,result_offsets=None,boundari
29
  from analyze_bsp_references import trace_fields
30
  from analyze_qvm_acceleration import FRAME,word,number
31
  handlers=handlers or {};result_offsets=result_offsets or {};points=[x['index']+2 for x in ins[start:stop] if x['opcode']=='CALL']+list(boundaries);pc=start;trace=[];calls=[];children=[];writes=[];ret=None
32
- bytes_map=dict(byte_inputs or {})
33
  for _ in range(256):
34
- if repeated_calls:bytes_map.update({FRAME+25+i:v&255 for i,v in enumerate(cmd)})
35
- t=trace_slice(ins,start,stop,m,{},resume_at=pc,stop_targets=points if repeated_calls else [p for p in points if p!=pc],byte_memory=bytes_map if repeated_calls else {**(byte_inputs or {}),**{FRAME+25+i:v&255 for i,v in enumerate(cmd)}},local_base=base,halt_on_leave=True,capture_stack=True,limit=8192,skip_initial_stop=repeated_calls);m=t['memory'];pc=t.get('stop',stop);trace+=t['trace'];calls+=t['calls'];writes+=t['byte_writes'];cmd=[t['byte_memory'][FRAME+25+i] for i in range(3)]
 
 
 
36
  if repeated_calls:
37
  bytes_map=t['byte_memory']
38
  if t['calls'] and t['stack'] and not (t['trace'] and ins[t['trace'][-1]]['opcode']=='LEAVE'):raise ValueError('nonempty bounded CALL return boundary')
@@ -41,8 +47,9 @@ def execute(ins,start,stop,m,cmd,base,handlers=None,result_offsets=None,boundari
41
  if c['target']==-107:value=word(math.sqrt(number(c['args'][8])));r={'input':c['args'][8]&0xffffffff,'root':value}
42
  else:
43
  if c['target'] not in handlers:raise ValueError('Unrecovered bounded child '+str(c['target']))
44
- m,cmd,value,r=handlers[c['target']](ins,m,c['args'],cmd)
45
  if sync_child_words:sync_words(child_before,m,bytes_map)
 
46
  if repeated_calls:patch_result(ins,c,m,bytes_map,base,value,result_offsets)
47
  elif ins[c['instruction']+1]['opcode']=='STORE4':
48
  dest=ins[c['instruction']-2];offset=result_offsets.get(c['instruction'])
@@ -52,6 +59,6 @@ def execute(ins,start,stop,m,cmd,base,handlers=None,result_offsets=None,boundari
52
  if t['trace'] and ins[t['trace'][-1]]['opcode']=='LEAVE':ret=t['stack'][-1];break
53
  if pc==stop or pc in boundaries:break
54
  else:raise ValueError('Bounded child loop exceeded')
55
- report={'return':ret,'calls':calls,'children':children,'byte_writes':writes,**trace_fields({'trace':trace},False)}
56
  if boundaries:report['stop']=pc
57
  return m,cmd,report
 
19
  m[0x30000+24]=sum((v&255)<<(8*(i+1)) for i,v in enumerate(cmd));return m
20
 
21
 
22
+ def execute(ins,start,stop,m,cmd,base,handlers=None,result_offsets=None,boundaries=(),byte_inputs=None,repeated_calls=False,sync_child_words=False,coherent_memory=False,byte_handlers=False,capture_byte_memory=False):
23
  """Bounded source calls with actual recovered children at empty-stack boundaries."""
24
+ from types import MappingProxyType
25
+ from qvm_byte_memory_support import write_bytes
26
+ if byte_handlers and not (coherent_memory and repeated_calls and sync_child_words):raise ValueError('byte handlers require coherent corrected synchronized mode')
27
  from qvm_child_memory_support import sync_words
28
  if sync_child_words and not repeated_calls:raise ValueError('child synchronization requires corrected reentry')
29
  import math
 
32
  from analyze_bsp_references import trace_fields
33
  from analyze_qvm_acceleration import FRAME,word,number
34
  handlers=handlers or {};result_offsets=result_offsets or {};points=[x['index']+2 for x in ins[start:stop] if x['opcode']=='CALL']+list(boundaries);pc=start;trace=[];calls=[];children=[];writes=[];ret=None
35
+ m=dict(m);bytes_map=dict(byte_inputs or {})
36
  for _ in range(256):
37
+ if repeated_calls:
38
+ command_bytes={FRAME+25+i:v&255 for i,v in enumerate(cmd)}
39
+ if coherent_memory:write_bytes(m,bytes_map,command_bytes)
40
+ else:bytes_map.update(command_bytes)
41
+ t=trace_slice(ins,start,stop,m,{},resume_at=pc,stop_targets=points if repeated_calls else [p for p in points if p!=pc],byte_memory=bytes_map if repeated_calls else {**(byte_inputs or {}),**{FRAME+25+i:v&255 for i,v in enumerate(cmd)}},local_base=base,halt_on_leave=True,capture_stack=True,limit=8192,skip_initial_stop=repeated_calls,coherent_memory=coherent_memory);m=t['memory'];pc=t.get('stop',stop);trace+=t['trace'];calls+=t['calls'];writes+=t['byte_writes'];cmd=[t['byte_memory'][FRAME+25+i] for i in range(3)]
42
  if repeated_calls:
43
  bytes_map=t['byte_memory']
44
  if t['calls'] and t['stack'] and not (t['trace'] and ins[t['trace'][-1]]['opcode']=='LEAVE'):raise ValueError('nonempty bounded CALL return boundary')
 
47
  if c['target']==-107:value=word(math.sqrt(number(c['args'][8])));r={'input':c['args'][8]&0xffffffff,'root':value}
48
  else:
49
  if c['target'] not in handlers:raise ValueError('Unrecovered bounded child '+str(c['target']))
50
+ m,cmd,value,r=handlers[c['target']](ins,m,c['args'],cmd,MappingProxyType(bytes_map)) if byte_handlers else handlers[c['target']](ins,m,c['args'],cmd)
51
  if sync_child_words:sync_words(child_before,m,bytes_map)
52
+ if byte_handlers:write_bytes(m,bytes_map,r.get('child_memory_bytes',{}))
53
  if repeated_calls:patch_result(ins,c,m,bytes_map,base,value,result_offsets)
54
  elif ins[c['instruction']+1]['opcode']=='STORE4':
55
  dest=ins[c['instruction']-2];offset=result_offsets.get(c['instruction'])
 
59
  if t['trace'] and ins[t['trace'][-1]]['opcode']=='LEAVE':ret=t['stack'][-1];break
60
  if pc==stop or pc in boundaries:break
61
  else:raise ValueError('Bounded child loop exceeded')
62
+ report={**({'byte_memory':bytes_map} if capture_byte_memory else {}),'return':ret,'calls':calls,'children':children,'byte_writes':writes,**trace_fields({'trace':trace},False)}
63
  if boundaries:report['stop']=pc
64
  return m,cmd,report
scripts/qvm_trace_support.py CHANGED
@@ -3,27 +3,31 @@ from analyze_deferred_auth import trace_slice
3
  from analyze_bsp_references import trace_fields
4
  from qvm_call_result_support import patch_result
5
 
6
- def resume(ins,start,stop,m,base,pc=None,handlers=None,boundaries=(),byte_inputs=None,limit=8192,result_offsets=None,repeated_calls=False,sync_child_words=False,segment_limit=512):
7
  if type(segment_limit) is not int or not 1<=segment_limit<=8192:raise ValueError('invalid bounded segment budget')
 
 
 
8
  from qvm_child_memory_support import sync_words
9
  if sync_child_words and not repeated_calls:raise ValueError('child synchronization requires corrected reentry')
10
  handlers=handlers or {};pc=start if pc is None else pc;m=dict(m);trace=[];calls=[];children=[];writes=[];bytes_map=dict(byte_inputs or {});ret=None
11
  points=[i['index']+2 for i in ins[start:stop] if i['opcode']=='CALL']+list(boundaries)
12
  for _ in range(segment_limit):
13
- t=trace_slice(ins,start,stop,m,{},resume_at=pc,stop_targets=points if repeated_calls else [p for p in points if p!=pc],local_base=base,byte_memory=bytes_map,halt_on_leave=True,capture_stack=True,limit=limit,skip_initial_stop=repeated_calls);m=t['memory'];pc=t.get('stop',stop);trace+=t['trace'];calls+=t['calls'];writes+=t['byte_writes'];bytes_map=t['byte_memory']
14
  if repeated_calls and t['calls'] and t['stack'] and not (t['trace'] and ins[t['trace'][-1]]['opcode']=='LEAVE'):
15
  raise ValueError('nonempty bounded CALL return boundary')
16
  for c in t['calls']:
17
  child_before=dict(m) if sync_child_words else None
18
  if c['target'] not in handlers:raise ValueError('Unrecovered trace child '+str(c['target']))
19
- m,value,e=handlers[c['target']](ins,m,c['args'])
20
  if sync_child_words:sync_words(child_before,m,bytes_map)
 
21
  patch_result(ins,c,m,bytes_map,base,value,result_offsets)
22
  children.append({'call':c,'effect':e})
23
  if t['trace'] and ins[t['trace'][-1]]['opcode']=='LEAVE':ret=t['stack'][-1];break
24
  if pc==stop or pc in boundaries:break
25
  else:raise ValueError('Trace segment budget exceeded')
26
- return m,{'stop':pc,'return':ret,'calls':calls,'children':children,'byte_writes':writes,**trace_fields({'trace':trace},False)}
27
 
28
  def captured(target,requests):
29
  def call(ins,m,args):
 
3
  from analyze_bsp_references import trace_fields
4
  from qvm_call_result_support import patch_result
5
 
6
+ def resume(ins,start,stop,m,base,pc=None,handlers=None,boundaries=(),byte_inputs=None,limit=8192,result_offsets=None,repeated_calls=False,sync_child_words=False,segment_limit=512,coherent_memory=False,byte_handlers=False,capture_byte_memory=False):
7
  if type(segment_limit) is not int or not 1<=segment_limit<=8192:raise ValueError('invalid bounded segment budget')
8
+ from types import MappingProxyType
9
+ from qvm_byte_memory_support import write_bytes
10
+ if byte_handlers and not (coherent_memory and repeated_calls and sync_child_words):raise ValueError('byte handlers require coherent corrected synchronized mode')
11
  from qvm_child_memory_support import sync_words
12
  if sync_child_words and not repeated_calls:raise ValueError('child synchronization requires corrected reentry')
13
  handlers=handlers or {};pc=start if pc is None else pc;m=dict(m);trace=[];calls=[];children=[];writes=[];bytes_map=dict(byte_inputs or {});ret=None
14
  points=[i['index']+2 for i in ins[start:stop] if i['opcode']=='CALL']+list(boundaries)
15
  for _ in range(segment_limit):
16
+ t=trace_slice(ins,start,stop,m,{},resume_at=pc,stop_targets=points if repeated_calls else [p for p in points if p!=pc],local_base=base,byte_memory=bytes_map,halt_on_leave=True,capture_stack=True,limit=limit,skip_initial_stop=repeated_calls,coherent_memory=coherent_memory);m=t['memory'];pc=t.get('stop',stop);trace+=t['trace'];calls+=t['calls'];writes+=t['byte_writes'];bytes_map=t['byte_memory']
17
  if repeated_calls and t['calls'] and t['stack'] and not (t['trace'] and ins[t['trace'][-1]]['opcode']=='LEAVE'):
18
  raise ValueError('nonempty bounded CALL return boundary')
19
  for c in t['calls']:
20
  child_before=dict(m) if sync_child_words else None
21
  if c['target'] not in handlers:raise ValueError('Unrecovered trace child '+str(c['target']))
22
+ m,value,e=handlers[c['target']](ins,m,c['args'],MappingProxyType(bytes_map)) if byte_handlers else handlers[c['target']](ins,m,c['args'])
23
  if sync_child_words:sync_words(child_before,m,bytes_map)
24
+ if byte_handlers:write_bytes(m,bytes_map,e.get('child_memory_bytes',{}))
25
  patch_result(ins,c,m,bytes_map,base,value,result_offsets)
26
  children.append({'call':c,'effect':e})
27
  if t['trace'] and ins[t['trace'][-1]]['opcode']=='LEAVE':ret=t['stack'][-1];break
28
  if pc==stop or pc in boundaries:break
29
  else:raise ValueError('Trace segment budget exceeded')
30
+ return m,{**({'byte_memory':bytes_map} if capture_byte_memory else {}),'stop':pc,'return':ret,'calls':calls,'children':children,'byte_writes':writes,**trace_fields({'trace':trace},False)}
31
 
32
  def captured(target,requests):
33
  def call(ins,m,args):
scripts/test_qvm_child_byte_effects.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json,unittest
2
+ from pathlib import Path
3
+ from qvm_trace_support import resume
4
+ from qvm_research_support import execute
5
+ from analyze_qvm_reentry_witness import instructions,BASE
6
+ from analyze_qvm_acceleration import FRAME
7
+ class ChildByteEffectsTests(unittest.TestCase):
8
+ def test_independent_override_precedence_and_mirrored_word(self):
9
+ ps=json.loads(Path('docs/research/qvm-child-byte-effects.json').read_text())['probes'];self.assertEqual(len(ps),40)
10
+ for p in ps:
11
+ b=bytearray.fromhex('88776655');b[p['lane']]=p['byte'];self.assertEqual(p['result'],int.from_bytes(b,'little'));self.assertEqual(p['stored'],p['result']);self.assertTrue(p['locked'])
12
+ def test_explicit_mode_required(self):
13
+ with self.assertRaisesRegex(ValueError,'byte handlers require'):resume([],0,0,{},0,byte_handlers=True)
14
+ def test_movement_tuple_has_command_precedence(self):
15
+ ins=instructions([('CONST',99),('CALL',None),('POP',None),('CONST',FRAME+25),('LOAD1',None),('LEAVE',0)])
16
+ def child(i,m,a,c,b):return m,[7,0,0],0,{'child_memory_bytes':{FRAME+25:99}}
17
+ _,cmd,e=execute(ins,0,len(ins),{},[0,0,0],BASE,{99:child},repeated_calls=True,sync_child_words=True,coherent_memory=True,byte_handlers=True);self.assertEqual((cmd,e['return']),([7,0,0],7))
18
+ if __name__=='__main__':unittest.main()
xtask/checks.tsv CHANGED
@@ -1894,3 +1894,7 @@ edge docs/research/qvm-coherent-memory.json scripts/test_qvm_coherent_memory.py
1894
  group coherent-memory scripts/analyze_qvm_coherent_memory.py
1895
  edge scripts/analyze_qvm_coherent_memory.py scripts/analyze_qvm_resumer_audit.py
1896
  edge scripts/qvm_byte_memory_support.py scripts/analyze_qvm_resumer_audit.py
 
 
 
 
 
1894
  group coherent-memory scripts/analyze_qvm_coherent_memory.py
1895
  edge scripts/analyze_qvm_coherent_memory.py scripts/analyze_qvm_resumer_audit.py
1896
  edge scripts/qvm_byte_memory_support.py scripts/analyze_qvm_resumer_audit.py
1897
+ report scripts/analyze_qvm_child_byte_effects.py docs/research/qvm-child-byte-effects.json
1898
+ edge docs/research/qvm-child-byte-effects.json scripts/test_qvm_child_byte_effects.py
1899
+ group child-byte-effects scripts/analyze_qvm_child_byte_effects.py
1900
+ edge scripts/analyze_qvm_child_byte_effects.py scripts/analyze_qvm_resumer_audit.py