yangchao
yangchao

Reputation: 53

how to use visual studio debugging sub process?

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

Answers (2)

Zhaoquan Huang
Zhaoquan Huang

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

RbMm
RbMm

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

Related Questions