Reputation: 53
I want to debugging a process B which started by process A,Bug when I attched process B,I can`t break on main function. Is there a way auto break when process B started?
Upvotes: 0
Views: 2172
Reputation: 56
When you manually attach to process B, it must have already run for some time.
With the plugin "Microsoft Child Process Debugging Power Tool", VS can automatically attach to child processes when they start, and you can break at the first statement in main()
.
Upvotes: 1
Reputation: 33716
unfortunately no way with visual-studio. at first and main - this debugger can not debug several processes at once. it can debug only one process. if you debug process A and it started process B - this debugger simply can not debug new process B.
in general when we debug process A - exist DebugPort
object attached to process. ( EPROCESS.DebugPort
) also in EPROCESS
object exist NoDebugInherit
flag. when process A start new process B - system do next (pseudo code):
if (Process->DebugPort && !Process->NoDebugInherit)
AttachDebugPortToNewProcess(Process->DebugPort);
if A under debugger and NoDebugInherit
flag not set - new process B also attached to the same DebugPort
(same debugger).
how is NoDebugInherit
is set ?
if we start process via CreateProcess
api - if we set DEBUG_ONLY_THIS_PROCESS
the NoDebugInherit
set to true. if we use DEBUG_PROCESS
without DEBUG_ONLY_THIS_PROCESS
- NoDebugInherit
set to false - as result all child processes created by the new process will be also debugged.
if we attach to already running process via DebugActiveProcess
NoDebugInherit
set to true. as result if this process start new process - it will be not debugged.
and we can query and set this NoDebugInherit
via NtQueryInformationProcess
and NtSetInformationProcess
with ProcessDebugFlags
PROCESSINFOCLASS
(it declared in ntddk.h). with this we can at any time query and change ProcessDebugFlags
by next code:
// from WRK\WRK-v1.2\public\sdk\inc\ntpsapi.h
//
// Define process debug flags
//
#define PROCESS_DEBUG_INHERIT 0x00000001
NTSTATUS SetDebugInherit(HANDLE hProcess, BOOLEAN bInherit)
{
ULONG DebugFlags;
// hProcess must have PROCESS_QUERY_INFORMATION access
NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessDebugFlags, &DebugFlags, sizeof(DebugFlags), 0);
if (0 <= status)
{
bInherit ? DebugFlags |= PROCESS_DEBUG_INHERIT : DebugFlags &= ~PROCESS_DEBUG_INHERIT;
// hProcess must have PROCESS_SET_INFORMATION access
status = NtSetInformationProcess(hProcess, ProcessDebugFlags, &DebugFlags, sizeof(DebugFlags));
}
return status;
}
if return back to MSVS or WinDbg - it always start new process with DEBUG_ONLY_THIS_PROCESS
. even if we yourself set NoDebugInherit
to false and start new process - anyway new process will be not debugged and even not run if we use MSVS. in case WinDbg try formal debug 2 (and more) processes at once but can not do this too. you need have better debugger which designed to debug multiple processes in concurrent.
another possibility set break-point in CreateProcessInternalW
in process A and after it hit - set break-point to NtResumeThread
(this must be temporary breakpoint - after CreateProcessInternalW
hit only). when NtResumeThread
hit - new process B
is started already (in suspended state). at this point you can run new instance of MSVS or WinDbg and attach to it. however here also can be problems, because most debuggers (MSVS and WinDbg) use DebugActiveProcess
. this api after call NtDebugActiveProcess
which is need and enough for begin debug process, by some reason create (DbgUiIssueRemoteBreakin
) new thread in target process (DbgUiRemoteBreakin
). as result new process begin executed on this thread. in xp this leads to process initialization fail. in modern windows - this is in general worked, but anyway can affect process execution - main process thread became not first in process.
if B is your process - so you can modify it code, you always can do next in point, where you want attach/break debugger:
while (!IsDebuggerPresent()) Sleep(1000);
__debugbreak();
or if you can show gui:
WCHAR sz[64];
swprintf(sz, L"attact to %u(0x%x)\n", GetCurrentProcessId(), GetCurrentProcessId());
while (!IsDebuggerPresent()) MessageBoxW(0,0,sz, MB_ICONINFORMATION);
__debugbreak();
Upvotes: 1