void LLDBConnector::Interrupt(eInterruptReason reason) { LLDBCommand command; command.SetCommandType(kCommandInterrupt); command.SetInterruptReason( reason ); SendCommand( command ); }
void CodeLiteLLDBApp::EvalExpression(const LLDBCommand& command) { wxPrintf("codelite-lldb: evaluating expression '%s'\n", command.GetExpression()); if ( CanInteract() ) { lldb::SBExpressionOptions options; lldb::SBValue value = m_target.EvaluateExpression( command.GetExpression().mb_str(wxConvUTF8).data(), options); if ( value.IsValid() ) { LLDBReply reply; reply.SetReplyType( kReplyTypeExprEvaluated ); reply.SetExpression( command.GetExpression() ); LLDBVariable::Vect_t vars; LLDBVariable::Ptr_t var( new LLDBVariable( value ) ); vars.push_back( var ); reply.SetVariables( vars ); // Cache the expanded variable (we will need it later for tooltip expansion m_variables.insert( std::make_pair(value.GetID(), value) ); SendReply( reply ); } } }
void LLDBConnector::DeleteAllBreakpoints() { if ( !IsRunning() ) { m_pendingDeletionBreakpoints.clear(); m_breakpoints.clear(); LLDBEvent event(wxEVT_LLDB_BREAKPOINTS_UPDATED); event.SetBreakpoints( GetAllBreakpoints() ); ProcessEvent( event ); return; } // mark all breakpoints for deletion CL_DEBUGS(wxString () << "codelite: DeleteAllBreakpoints called"); m_pendingDeletionBreakpoints.swap( m_breakpoints ); if ( !IsCanInteract() ) { Interrupt( kInterruptReasonDeleteAllBreakpoints ); } else { LLDBCommand command; command.SetCommandType(kCommandDeleteAllBreakpoints); SendCommand( command ); m_pendingDeletionBreakpoints.clear(); } }
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(); }
void CodeLiteLLDBApp::EvalExpression(const LLDBCommand& command) { wxPrintf("codelite-lldb: evaluating expression '%s'\n", command.GetExpression()); if(CanInteract()) { // Evaluate the expression based on the current frame wxString expression = command.GetExpression(); expression.Trim().Trim(false); lldb::SBValue value = m_target.GetProcess().GetSelectedThread().GetSelectedFrame().GetValueForVariablePath( expression.mb_str(wxConvUTF8).data()); if(value.IsValid()) { LLDBReply reply; reply.SetReplyType(kReplyTypeExprEvaluated); reply.SetExpression(command.GetExpression()); LLDBVariable::Vect_t vars; LLDBVariable::Ptr_t var(new LLDBVariable(value)); vars.push_back(var); reply.SetVariables(vars); VariableWrapper wrapper; wrapper.value = value; // Cache the expanded variable (we will need it later for tooltip expansion m_variables.insert(std::make_pair(value.GetID(), wrapper)); SendReply(reply); } } }
void LLDBConnector::NextInstruction() { if(IsCanInteract()) { LLDBCommand command; command.SetCommandType(kCommandNextInstruction); SendCommand(command); } }
void LLDBConnector::ShowCurrentFileLine() { if(IsCanInteract()) { LLDBCommand command; command.SetCommandType(kCommandCurrentFileLine); SendCommand(command); } }
void LLDBConnector::RequestLocals() { if(IsCanInteract()) { LLDBCommand command; command.SetCommandType(kCommandGetLocals); SendCommand(command); } }
void MainDialog::OnStart(wxCommandEvent& event) { LLDBCommand command; command.SetCommandType( kCommandStart ); command.SetExecutable( m_filePickerExe->GetPath() ); m_connector.SendCommand( command ); LogCommand( command ); }
void LLDBConnector::SelectFrame(int frameID) { if(IsCanInteract()) { LLDBCommand command; command.SetCommandType(kCommandSelectFrame); command.SetFrameId(frameID); SendCommand(command); } }
void LLDBConnector::SelectThread(int threadID) { if(IsCanInteract()) { LLDBCommand command; command.SetCommandType(kCommandSelectThread); command.SetThreadId(threadID); SendCommand(command); } }
void CodeLiteLLDBApp::SelectFrame(const LLDBCommand& command) { wxPrintf("codelite-lldb: selecting frame %d\n", command.GetFrameId()); if(CanInteract() && command.GetFrameId() != wxNOT_FOUND) { m_target.GetProcess().GetSelectedThread().SetSelectedFrame(command.GetFrameId()); m_interruptReason = kInterruptReasonNone; NotifyStopped(); } }
void LLDBConnector::EvaluateExpression(const wxString& expression) { if(IsCanInteract()) { LLDBCommand command; command.SetCommandType(kCommandEvalExpression); command.SetExpression(expression); SendCommand(command); } }
void LLDBConnector::RequestVariableChildren(int lldbId) { if(IsCanInteract()) { LLDBCommand command; command.SetCommandType(kCommandExpandVariable); command.SetLldbId(lldbId); SendCommand(command); } }
void LLDBConnector::Stop() { if(IsAttachedToProcess()) { Detach(); } else { LLDBCommand command; command.SetCommandType(kCommandStop); SendCommand(command); } }
void MainDialog::OnLLDBStarted(LLDBEvent& e) { e.Skip(); m_textCtrlLog->AppendText(wxString() << "LLDB Started successfully\n"); LLDBCommand command; command.SetCommandType( kCommandRun ); command.SetCommandArguments( "" ); m_connector.SendCommand( command ); m_textCtrlLog->AppendText("Running...\n"); }
void CodeLiteLLDBApp::SelectThread(const LLDBCommand& command) { wxPrintf("codelite-lldb: selecting thread %d\n", command.GetThreadId()); if(CanInteract() && command.GetThreadId() != wxNOT_FOUND) { lldb::SBThread thr = m_target.GetProcess().GetThreadByID(command.GetThreadId()); if(thr.IsValid()) { m_target.GetProcess().SetSelectedThread(thr); m_interruptReason = kInterruptReasonNone; NotifyStopped(); } } }
void LLDBConnector::Detach() { if(IsCanInteract()) { CL_DEBUG("Sending 'Detach' command"); LLDBCommand command; command.SetCommandType(kCommandDetach); SendCommand(command); } else { Interrupt(kInterruptReasonDetaching); } }
void LLDBConnector::Start(const LLDBCommand& runCommand) { LLDBCommand startCommand; startCommand.SetExecutable( runCommand.GetExecutable() ); startCommand.SetCommandType( kCommandStart ); SendCommand( startCommand ); // stash the runCommand for the future 'Run()' call m_runCommand.Clear(); m_runCommand = runCommand; m_runCommand.SetCommandType( kCommandRun ); }
void LLDBConnector::SendCommand(const LLDBCommand& command) { try { if(m_socket) { // Convert local paths to remote paths if needed LLDBCommand updatedCommand = command; updatedCommand.UpdatePaths(m_pivot); m_socket->WriteMessage(updatedCommand.ToJSON().format()); } } catch(clSocketException& e) { wxUnusedVar(e); } }
void LLDBPlugin::OnDebugAttachToProcess(clDebugEvent& event) { if(event.GetDebuggerName() != LLDB_DEBUGGER_NAME) { event.Skip(); return; } #ifdef __WXMSW__ ::wxMessageBox( _("Attach to process with LLDB is not supported under Windows"), "CodeLite", wxOK | wxCENTER | wxICON_WARNING); return; #endif wxString terminalTitle; terminalTitle << "Console PID " << event.GetInt(); if(!DoInitializeDebugger(event, true, terminalTitle)) return; LLDBConnectReturnObject retObj; LLDBSettings settings; settings.Load(); if(m_connector.Connect(retObj, settings, 5)) { // Apply the environment EnvSetter env; // remove all breakpoints from previous session m_connector.DeleteAllBreakpoints(); LLDBSettings settings; settings.Load(); // Attach to the process LLDBCommand command; command.SetCommandType(kCommandAttachProcess); command.SetProcessID(event.GetInt()); command.SetSettings(settings); m_connector.AttachProcessWithPID(command); } else { // Failed to connect, notify and perform cleanup DoCleanup(); wxString message; message << _("Could not connect to codelite-lldb at '") << m_connector.GetConnectString() << "'"; ::wxMessageBox(message, "CodeLite", wxICON_ERROR | wxOK | wxCENTER); return; } }
void LLDBConnector::ApplyBreakpoints() { if(!m_breakpoints.empty()) { if(IsCanInteract()) { LLDBCommand command; command.SetCommandType(kCommandApplyBreakpoints); command.SetBreakpoints(GetUnappliedBreakpoints()); SendCommand(command); m_breakpoints.clear(); } else { Interrupt(kInterruptReasonApplyBreakpoints); } } }
void LLDBConnector::DeleteBreakpoints() { if ( IsCanInteract() ) { CL_DEBUGS(wxString () << "codelite: deleting breakpoints (total of " << m_pendingDeletionBreakpoints.size() << " breakpoints)"); LLDBCommand command; command.SetCommandType( kCommandDeleteBreakpoint ); command.SetBreakpoints( m_pendingDeletionBreakpoints ); SendCommand( command ); CL_DEBUGS(wxString () << "codelite: DeleteBreakpoints celar pending deletionbreakpoints queue"); m_pendingDeletionBreakpoints.clear(); } else { CL_DEBUG("codelite: interrupting codelite-lldb for kInterruptReasonDeleteBreakpoint"); Interrupt( kInterruptReasonDeleteBreakpoint ); } }
void CodeLiteLLDBApp::DeleteBreakpoints(const LLDBCommand& command) { CHECK_DEBUG_SESSION_RUNNING(); const LLDBBreakpoint::Vec_t& bps = command.GetBreakpoints(); if(bps.empty()) { return; } wxPrintf("codelite-lldb: DeleteBreakpoints called\n"); if(m_target.GetProcess().GetState() == lldb::eStateStopped) { wxPrintf("codelite-lldb: DeleteBreakpoints: process state is Stopped - will apply them now\n"); for(size_t i = 0; i < bps.size(); ++i) { LLDBBreakpoint::Ptr_t breakpoint = bps.at(i); wxPrintf("codelite-lldb: deleting breakpoint: %s\n", breakpoint->ToString()); if(breakpoint->IsApplied()) { lldb::SBBreakpoint lldbBreakpoint = m_target.FindBreakpointByID(breakpoint->GetId()); if(lldbBreakpoint.IsValid()) { lldbBreakpoint.ClearAllBreakpointSites(); m_target.BreakpointDelete(lldbBreakpoint.GetID()); } } } NotifyBreakpointsUpdated(); } else { wxPrintf("codelite-lldb: DeleteBreakpoints: process is Busy - will interrupt it\n"); m_interruptReason = kInterruptReasonDeleteBreakpoint; m_target.GetProcess().SendAsyncInterrupt(); } }
void CodeLiteLLDBApp::ApplyBreakpoints(const LLDBCommand& command) { wxPrintf("codelite-lldb: ApplyBreakpoints called\n"); if ( m_target.GetProcess().GetState() == lldb::eStateStopped ) { wxPrintf("codelite-lldb: ApplyBreakpoints: process state is stopped - will apply them now\n"); // we can apply the breakpoints // Apply all breakpoints with an-invalid breakpoint ID LLDBBreakpoint::Vec_t breakpoints = command.GetBreakpoints(); while( !breakpoints.empty() ) { LLDBBreakpoint::Ptr_t breakPoint = breakpoints.at(0); if ( !breakPoint->IsApplied() ) { switch( breakPoint->GetType() ) { case LLDBBreakpoint::kFunction: { wxPrintf("codelite-lldb: creating breakpoint by name: %s\n", breakPoint->GetName()); m_target.BreakpointCreateByName(breakPoint->GetName().mb_str().data(), NULL); break; } case LLDBBreakpoint::kFileLine: { wxPrintf("codelite-lldb: creating breakpoint by location: %s,%d\n", breakPoint->GetFilename(), breakPoint->GetLineNumber()); m_target.BreakpointCreateByLocation(breakPoint->GetFilename().mb_str().data(), breakPoint->GetLineNumber()); break; } } } breakpoints.erase(breakpoints.begin()); } NotifyBreakpointsUpdated(); } else { wxPrintf("codelite-lldb: ApplyBreakpoints: process state is _NOT_ Stopped - interrupting process\n"); // interrupt the process m_interruptReason = kInterruptReasonApplyBreakpoints; m_target.GetProcess().SendAsyncInterrupt(); } }
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 LLDBConnector::SendCommand(const LLDBCommand& command) { try { if ( m_socket ) { m_socket->WriteMessage( command.ToJSON().format() ); } } catch ( clSocketException &e ) { wxUnusedVar( e ); } }
// we need to return list of children for a variable // we stashed the variables we got so far inside a map void CodeLiteLLDBApp::ExpandVariable(const LLDBCommand& command) { int variableId = command.GetLldbId(); if(variableId == wxNOT_FOUND) { return; } LLDBVariable::Vect_t children; std::map<int, VariableWrapper>::iterator iter = m_variables.find(variableId); if(iter != m_variables.end()) { lldb::SBValue* pvalue = &(iter->second.value); lldb::SBValue deReferencedValue; int size = pvalue->GetNumChildren(); lldb::TypeClass typeClass = pvalue->GetType().GetTypeClass(); if(typeClass & lldb::eTypeClassArray) { size > (int)m_settings.GetMaxArrayElements() ? size = m_settings.GetMaxArrayElements() : size = size; wxPrintf("codelite-lldb: value %s is an array. Limiting its size\n", pvalue->GetName()); } /*else if ( typeClass & lldb::eTypeClassPointer ) { // dereference is needed wxPrintf("codelite-lldb: value '%s' is a class pointer, dereferecning it\n", pvalue->GetName()); deReferencedValue = pvalue->Dereference(); // and update the number of children pvalue = &deReferencedValue; wxPrintf("codelite-lldb: new number of children is set to %d\n", size); size = pvalue->GetNumChildren(); }*/ for(int i = 0; i < size; ++i) { lldb::SBValue child = pvalue->GetChildAtIndex(i); if(child.IsValid()) { LLDBVariable::Ptr_t var(new LLDBVariable(child)); children.push_back(var); VariableWrapper wrapper; wrapper.value = child; m_variables.insert(std::make_pair(child.GetID(), wrapper)); } } LLDBReply reply; reply.SetReplyType(kReplyTypeVariableExpanded); reply.SetVariables(children); reply.SetLldbId(variableId); SendReply(reply); } }
void LLDBPlugin::OnDebugQuickDebug(clDebugEvent& event) { #ifdef __WXMSW__ ::wxMessageBox( _("Quick Debug with LLDB is not supported under Windows"), "CodeLite", wxOK | wxCENTER | wxICON_WARNING); return; #endif if(!DoInitializeDebugger(event, true)) { return; } LLDBConnectReturnObject retObj; LLDBSettings settings; settings.Load(); if(m_connector.Connect(retObj, settings, 5)) { // Apply the environment EnvSetter env; // Get list of breakpoints and add them ( we will apply them later on ) BreakpointInfo::Vec_t gdbBps; m_mgr->GetAllBreakpoints(gdbBps); // remove all breakpoints from previous session m_connector.DeleteAllBreakpoints(); // apply the serialized breakpoints // In 'Quick Debug' we stop on main m_connector.AddBreakpoint("main"); m_connector.AddBreakpoints(gdbBps); LLDBCommand startCommand; startCommand.FillEnvFromMemory(); startCommand.SetExecutable(event.GetExecutableName()); startCommand.SetCommandArguments(event.GetArguments()); startCommand.SetWorkingDirectory(event.GetWorkingDirectory()); startCommand.SetStartupCommands(event.GetStartupCommands()); startCommand.SetRedirectTTY(m_terminalTTY); m_connector.Start(startCommand); } else { // Failed to connect, notify and perform cleanup DoCleanup(); wxString message; message << _("Could not connect to codelite-lldb at '") << m_connector.GetConnectString() << "'"; ::wxMessageBox(message, "CodeLite", wxICON_ERROR | wxOK | wxCENTER); return; } }