Res ThreadScan(ScanState ss, Thread thread, void *stackBot) { DWORD id; Res res; id = GetCurrentThreadId(); if(id != thread->id) { /* .thread.id */ CONTEXT context; BOOL success; Addr *stackBase, *stackLimit, stackPtr; /* scan stack and register roots in other threads */ /* This dumps the relevant registers into the context */ /* .context.flags */ context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; /* .thread.handle.get-context */ success = GetThreadContext(thread->handle, &context); if(!success) { /* .error.get-context */ /* We assume that the thread must have been destroyed. */ /* We ignore the situation by returning immediately. */ return ResOK; } stackPtr = (Addr)context.Esp; /* .i3.sp */ /* .stack.align */ stackBase = (Addr *)AddrAlignUp(stackPtr, sizeof(Addr)); stackLimit = (Addr *)stackBot; if (stackBase >= stackLimit) return ResOK; /* .stack.below-bottom */ /* scan stack inclusive of current sp and exclusive of * stackBot (.stack.full-descend) */ res = TraceScanAreaTagged(ss, stackBase, stackLimit); if(res != ResOK) return res; /* (.context.regroots) * This scans the root registers (.context.regroots). It also * unnecessarily scans the rest of the context. The optimisation * to scan only relevant parts would be machine dependent. */ res = TraceScanAreaTagged(ss, (Addr *)&context, (Addr *)((char *)&context + sizeof(CONTEXT))); if(res != ResOK) return res; } else { /* scan this thread's stack */ res = StackScan(ss, stackBot); if(res != ResOK) return res; } return ResOK; }
Res ThreadScan(ScanState ss, Thread thread, void *stackBot) { UNUSED(thread); return StackScan(ss, stackBot); }