// For local debugging, NetBSD will override the debug logic to use llgs-launch // rather than lldb-launch, llgs-attach. This differs from current lldb- // launch, debugserver-attach approach on MacOSX. lldb::ProcessSP PlatformNetBSD::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new // target, else use existing one Status &error) { Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); LLDB_LOG(log, "target {0}", target); // If we're a remote host, use standard behavior from parent class. if (!IsHost()) return PlatformPOSIX::DebugProcess(launch_info, debugger, target, error); // // For local debugging, we'll insist on having ProcessGDBRemote create the // process. // ProcessSP process_sp; // Make sure we stop at the entry point launch_info.GetFlags().Set(eLaunchFlagDebug); // We always launch the process we are going to debug in a separate process // group, since then we can handle ^C interrupts ourselves w/o having to // worry about the target getting them as well. launch_info.SetLaunchInSeparateProcessGroup(true); // Ensure we have a target. if (target == nullptr) { LLDB_LOG(log, "creating new target"); TargetSP new_target_sp; error = debugger.GetTargetList().CreateTarget( debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp); if (error.Fail()) { LLDB_LOG(log, "failed to create new target: {0}", error); return process_sp; } target = new_target_sp.get(); if (!target) { error.SetErrorString("CreateTarget() returned nullptr"); LLDB_LOG(log, "error: {0}", error); return process_sp; } } // Mark target as currently selected target. debugger.GetTargetList().SetSelectedTarget(target); // Now create the gdb-remote process. LLDB_LOG(log, "having target create process with gdb-remote plugin"); process_sp = target->CreateProcess(launch_info.GetListener(), "gdb-remote", nullptr); if (!process_sp) { error.SetErrorString("CreateProcess() failed for gdb-remote process"); LLDB_LOG(log, "error: {0}", error); return process_sp; } LLDB_LOG(log, "successfully created process"); // Adjust launch for a hijacker. ListenerSP listener_sp; if (!launch_info.GetHijackListener()) { LLDB_LOG(log, "setting up hijacker"); listener_sp = Listener::MakeListener("lldb.PlatformNetBSD.DebugProcess.hijack"); launch_info.SetHijackListener(listener_sp); process_sp->HijackProcessEvents(listener_sp); } // Log file actions. if (log) { LLDB_LOG(log, "launching process with the following file actions:"); StreamString stream; size_t i = 0; const FileAction *file_action; while ((file_action = launch_info.GetFileActionAtIndex(i++)) != nullptr) { file_action->Dump(stream); LLDB_LOG(log, "{0}", stream.GetData()); stream.Clear(); } } // Do the launch. error = process_sp->Launch(launch_info); if (error.Success()) { // Handle the hijacking of process events. if (listener_sp) { const StateType state = process_sp->WaitForProcessToStop( llvm::None, NULL, false, listener_sp); LLDB_LOG(log, "pid {0} state {0}", process_sp->GetID(), state); } // Hook up process PTY if we have one (which we should for local debugging // with llgs). int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); if (pty_fd != PseudoTerminal::invalid_fd) { process_sp->SetSTDIOFileDescriptor(pty_fd); LLDB_LOG(log, "hooked up STDIO pty to process"); } else LLDB_LOG(log, "not using process STDIO pty"); } else { LLDB_LOG(log, "process launch failed: {0}", error); // FIXME figure out appropriate cleanup here. Do we delete the target? Do // we delete the process? Does our caller do that? } return process_sp; }