bool CodeLiteLLDBApp::InitializeLLDB(const LLDBCommand& command) { if(IsDebugSessionInProgress()) { wxPrintf("codelite-lldb: another session is already in progress\n"); return false; } if(!command.GetWorkingDirectory().IsEmpty()) { ::wxSetWorkingDirectory(command.GetWorkingDirectory()); } wxPrintf("codelite-lldb: working directory is set to %s\n", ::wxGetCwd()); #ifdef __WXMAC__ // On OSX, debugserver executable must exists otherwise lldb will not work properly // we ensure that it exists by checking the environment variable LLDB_DEBUGSERVER_PATH wxString lldbDebugServer; if(!::wxGetEnv("LLDB_DEBUGSERVER_PATH", &lldbDebugServer) || !wxFileName::Exists(lldbDebugServer)) { wxPrintf("codelite-lldb: LLDB_DEBUGSERVER_PATH environment does not exist or contains a path to a non existent " "file\n"); NotifyExited(); return false; } #endif m_debuggeePid = wxNOT_FOUND; wxPrintf("codelite-lldb: creating target for file '%s'\n", command.GetExecutable()); m_debugger = lldb::SBDebugger::Create(); lldb::SBError lldbError; m_target = m_debugger.CreateTarget(command.GetExecutable().mb_str().data(), NULL, NULL, true, lldbError); if(!m_target.IsValid()) { wxPrintf("codelite-lldb: could not create target for file %s. %s\n", command.GetExecutable(), lldbError.GetCString()); NotifyExited(); return false; } // Print the content of the summaries (for debugging purposes) wxPrintf("codelite-lldb: created target for %s\n", command.GetExecutable()); m_debugger.SetAsync(true); // Keep the settings m_settings = command.GetSettings(); // First, source the .lldbinit file wxString source_command; source_command << "command source '" << ::wxGetHomeDir() << "/.lldbinit" << "'"; DoExecutueShellCommand(source_command); // Apply the types lldb::SBCommandReturnObject ret; wxArrayString commands = ::wxStringTokenize(m_settings.GetTypes(), "\n", wxTOKEN_STRTOK); for(size_t i = 0; i < commands.GetCount(); ++i) { DoExecutueShellCommand(commands.Item(i)); } // DoExecutueShellCommand("type summary list"); return true; }
void CodeLiteLLDBApp::AttachProcess(const LLDBCommand& command) { wxPrintf("codeite-lldb: attaching to process with PID %d\n", command.GetProcessID()); if(!InitializeLLDB(command)) { return; } lldb::SBError errorCode; lldb::SBListener listener; lldb::SBProcess process = m_target.AttachToProcessWithID(listener, (lldb::pid_t)command.GetProcessID(), errorCode); if(!errorCode.Success()) { wxPrintf("codeite-lldb: error attaching process %d. '%s'\n", command.GetProcessID(), errorCode.GetCString()); NotifyExited(); return; } wxPrintf("codeite-lldb: process attached successfully\n"); // Launch the thread that will handle the LLDB process events m_lldbProcessEventThread = new LLDBProcessEventHandlerThread(this, m_debugger, m_target.GetProcess(), kDebugSessionTypeAttach); m_lldbProcessEventThread->Start(); // In any case, reset the interrupt reason m_interruptReason = kInterruptReasonNone; // Notify codelite that the debugger started successfully NotifyStarted(kDebugSessionTypeAttach); }
void CodeLiteLLDBApp::OpenCoreFile(const LLDBCommand& command) { wxPrintf("codeite-lldb: debugging core file '%s'\n", command.GetCorefile()); wxPrintf("codeite-lldb: executable file '%s'\n", command.GetExecutable()); if(!InitializeLLDB(command)) { return; } lldb::SBProcess process = m_target.LoadCore(command.GetCorefile().mb_str(wxConvUTF8).data()); if(!process.IsValid()) { wxPrintf("codeite-lldb: error loading core file '%s'\n", command.GetCorefile()); NotifyExited(); return; } // Launch the thread that will handle the LLDB process events m_lldbProcessEventThread = new LLDBProcessEventHandlerThread(this, m_debugger, m_target.GetProcess(), kDebugSessionTypeCore); m_lldbProcessEventThread->Start(); // Notify codelite that the debugger started successfully NotifyStarted(kDebugSessionTypeCore); // In any case, reset the interrupt reason m_interruptReason = kInterruptReasonNone; // Since we are in 'core' session // immediately notify about 'stop' NotifyStopped(); }
bool LLDBDebugger::Run( const wxString &in, const wxString& out, const wxString &err, const wxArrayString& argvArr, const wxArrayString& envArr, const wxString &workingDirectory) { if ( m_debugger.IsValid() ) { // Construct char** arrays const char** argv = (const char**)_wxArrayStringToCharPtrPtr(argvArr); const char** envp = (const char**)_wxArrayStringToCharPtrPtr(envArr); const char* pin = in.mb_str(wxConvUTF8).data(); const char* pout = out.mb_str(wxConvUTF8).data(); const char* perr = err.mb_str(wxConvUTF8).data(); const char* wd = workingDirectory.mb_str(wxConvUTF8).data(); lldb::SBError error; lldb::SBListener listener = m_debugger.GetListener(); bool isOk = m_target.Launch(listener, argv, envp, pin, pout, perr, wd, 0, false, error).IsValid(); _deleteCharPtrPtr( const_cast<char**>(argv) ); _deleteCharPtrPtr( const_cast<char**>(envp) ); if ( !isOk ) { Cleanup(); NotifyExited(); } return isOk; } return false; }
void LLDBDebugger::OnTimer(wxTimerEvent& e) { if ( m_debugger.IsValid() ) { lldb::SBEvent lldbEvent; if ( m_debugger.GetListener().WaitForEvent(0, lldbEvent) ) { if ( lldbEvent.IsValid() ) { lldb::StateType state = m_target.GetProcess().GetStateFromEvent( lldbEvent ); switch ( state ) { case lldb::eStateStopped: NotifyBacktrace(); NotifyStopped(); break; case lldb::eStateConnected: break; case lldb::eStateLaunching: break; case lldb::eStateRunning: break; case lldb::eStateExited: Cleanup(); NotifyExited(); break; default: break; } } } } }
void LLDBDebugger::Stop(bool notifyExit) { wxDELETE(m_thread); m_target.GetProcess().Kill(); Cleanup(); if ( notifyExit ) { NotifyExited(); } }
void CodeLiteLLDBApp::DetachDebugger(const LLDBCommand& command) { // detach from the process wxPrintf("codelite-lldb: detaching from process\n"); m_target.DeleteAllBreakpoints(); m_target.DeleteAllWatchpoints(); if(m_target.GetProcess().IsValid()) { // detch and 'continue' m_target.GetProcess().Detach(false); } NotifyExited(); }
bool LLDBDebugger::Run( const wxString &in, const wxString& out, const wxString &err, const wxArrayString& argvArr, const wxArrayString& envArr, const wxString &workingDirectory) { if ( m_thread ) { return false; } if ( m_debugger.IsValid() ) { // Construct char** arrays const char** argv = (const char**)_wxArrayStringToCharPtrPtr(argvArr); const char** envp = (const char**)_wxArrayStringToCharPtrPtr(envArr); const char* pin = in.mb_str(wxConvUTF8).data(); const char* pout = out.mb_str(wxConvUTF8).data(); const char* perr = err.mb_str(wxConvUTF8).data(); const char* wd = workingDirectory.mb_str(wxConvUTF8).data(); wxUnusedVar(pin); wxUnusedVar(pout); wxUnusedVar(perr); lldb::SBLaunchInfo launchInfo(argv); lldb::SBError error; // Set the launch flags launchInfo.SetLaunchFlags(lldb::eLaunchFlagStopAtEntry | lldb::eLaunchFlagLaunchInSeparateProcessGroup); launchInfo.SetEnvironmentEntries(envp, false); launchInfo.SetWorkingDirectory(wd); launchInfo.AddOpenFileAction(STDIN_FILENO, pin, true, false); launchInfo.AddOpenFileAction(STDERR_FILENO, perr, false, true); launchInfo.AddOpenFileAction(STDOUT_FILENO, pout, false, true); bool isOk = m_target.Launch(launchInfo, error).IsValid(); //bool isOk = m_target.LaunchSimple(argv, envp, wd).IsValid(); _deleteCharPtrPtr( const_cast<char**>(argv) ); _deleteCharPtrPtr( const_cast<char**>(envp) ); if ( !isOk ) { Cleanup(); NotifyExited(); } m_debugeePid = m_target.GetProcess().GetProcessID(); m_thread = new LLDBDebuggerThread(this, m_debugger.GetListener(), m_target.GetProcess()); m_thread->Start(); return isOk; } return false; }
void CodeLiteLLDBApp::StopDebugger(const LLDBCommand& command) { CHECK_DEBUG_SESSION_RUNNING(); NotifyExited(); }
void CodeLiteLLDBApp::RunDebugger(const LLDBCommand& command) { if(m_debuggeePid != wxNOT_FOUND) { wxPrintf("codelite-lldb: another session is already in progress\n"); return; } if(m_debugger.IsValid()) { m_variables.clear(); m_watches.clear(); // Construct char** arrays clCommandLineParser parser(command.GetCommandArguments()); const char** argv = (const char**)_wxArrayStringToCharPtrPtr(parser.ToArray()); char** penv = command.GetEnvArray(); std::string tty_c; std::string workingDirectory; if(!command.GetRedirectTTY().IsEmpty()) { tty_c = command.GetRedirectTTY().mb_str(wxConvUTF8).data(); } if(!command.GetWorkingDirectory().IsEmpty()) { workingDirectory = command.GetWorkingDirectory().mb_str(wxConvUTF8).data(); } const char* ptty = tty_c.empty() ? NULL : tty_c.c_str(); wxPrintf("codelite-lldb: running debugger. tty=%s\n", ptty); const char* pwd = workingDirectory.empty() ? NULL : workingDirectory.c_str(); wxPrintf("codelite-lldb: target working directory is set to: %s\n", pwd ? pwd : "NULL"); // wxPrintf("codelite-lldb: Environment is set to:\n"); // print_c_array( (const char**)penv ); wxPrintf("codelite-lldb: Arguments are set to:\n"); print_c_array(argv); // Execute startup commands wxArrayString startupCommands = ::wxStringTokenize(command.GetStartupCommands(), "\n", wxTOKEN_STRTOK); for(size_t i = 0; i < startupCommands.GetCount(); ++i) { lldb::SBCommandReturnObject ret; std::string c_command = startupCommands.Item(i).Trim().mb_str(wxConvUTF8).data(); wxPrintf("codelite-lldb: executing: '%s'\n", c_command.c_str()); m_debugger.GetCommandInterpreter().HandleCommand(c_command.c_str(), ret); } lldb::SBError lldbError; lldb::SBListener listener = m_debugger.GetListener(); lldb::SBProcess process = m_target.Launch(listener, argv, (const char**)penv, ptty, ptty, ptty, pwd, lldb::eLaunchFlagLaunchInSeparateProcessGroup | lldb::eLaunchFlagStopAtEntry, true, lldbError); // bool isOk = m_target.LaunchSimple(argv, envp, wd).IsValid(); DELETE_CHAR_PTR_PTR(const_cast<char**>(argv)); DELETE_CHAR_PTR_PTR(penv); if(!process.IsValid() || !lldbError.Success()) { wxPrintf("codelite-lldb: error while launching process. %s\n", lldbError.GetCString()); NotifyExited(); } else { m_debuggeePid = process.GetProcessID(); NotifyRunning(); } } }
void LLDBDebugger::Stop() { m_target.GetProcess().Kill(); Cleanup(); NotifyExited(); }