re: WaitMultiple read confirmed on a live capture; XTimer is a third type
23 wait frames, 30 objects, nothing unresolved -- the second deref turns every former miss into a resolved object, as predicted. XEvent 20 / XSemaphore 9 / XTimer 1; every WaitMultiple thread waits on a pair, and 78/79/80 and 64/65 are worker groups sharing a handle. %ebp does not survive as the count -- WaitMultiple reuses it at 8fc158 -- so the array is bounded by reading until an entry stops resolving instead. The frozen capture is still not taken: screen_id reads 'flight' at the second capture and out to ~470s, so the mission never black-screened. The diff in the data file is two healthy captures and is recorded as such.
This commit is contained in:
@@ -6,7 +6,12 @@ freeze_waitobj.sh), so they are parsed separately:
|
||||
|
||||
Wait rbx = this -> [rbx] is the vtable
|
||||
WaitMultiple rbx = XObject** -> [[rbx+8i]] is object i's vtable
|
||||
ebp = count -> entries past the count are garbage
|
||||
|
||||
%ebp holds the count only at the prologue: WaitMultiple reuses it at 8fc158
|
||||
(`mov 0x10(%rax),%ebp`), and it reads 0 at the point these captures interrupt.
|
||||
So the array length is NOT taken from a register -- entries are read until one
|
||||
stops resolving, which is the same self-validating rule used for everything
|
||||
else here.
|
||||
|
||||
Every reading is validated the same way: gdb's `info symbol` must resolve it to
|
||||
a `vtable for ...` symbol. A polymorphic object's first word always is one, so
|
||||
@@ -50,14 +55,16 @@ def report(tag):
|
||||
if not recs: return collections.Counter()
|
||||
tally = collections.Counter()
|
||||
for r in recs:
|
||||
n = r['count'] if r['kind'] == 'WaitMultiple' and r['count'] else len(r['slots'])
|
||||
n = min(n, len(r['slots']))
|
||||
live = r['slots'][:n]
|
||||
# take entries up to the first one that did not resolve
|
||||
live = []
|
||||
for s_ in r['slots']:
|
||||
if s_ is None: break
|
||||
live.append(s_)
|
||||
for s in live:
|
||||
tally[s if s else '<unresolved>'] += 1
|
||||
print(' T%-4s %-13s count=%-4s %s' % (
|
||||
r['th'], r['kind'], r['count'] if r['count'] is not None else '-',
|
||||
', '.join(s or '?' for s in live) or '(nothing readable)'))
|
||||
print(' T%-4s %-13s n=%d %s' % (
|
||||
r['th'], r['kind'], len(live),
|
||||
', '.join(live) or '(nothing readable)'))
|
||||
print(' --- objects waited on:')
|
||||
for k, c in tally.most_common():
|
||||
print(' %-45s %d' % (k, c))
|
||||
|
||||
Reference in New Issue
Block a user