Esempio n. 1
0
bool DbgGdb::Interrupt()
{
    if ( m_debuggeePid > 0 ) {
        m_observer->UpdateAddLine( wxString::Format( wxT( "Interrupting debugee process: %ld" ), m_debuggeePid ) );

#ifdef __WXMSW__
        if ( !GetIsRemoteDebugging() && DebugBreakProcessFunc ) {
            // we have DebugBreakProcess
            HANDLE process = OpenProcess( PROCESS_ALL_ACCESS, FALSE, ( DWORD )m_debuggeePid );
            BOOL res = DebugBreakProcessFunc( process );
            CloseHandle(process);
            return res == TRUE;
        }

        if ( GetIsRemoteDebugging() ) {
            // We need to send GDB a Ctrl-C event.  Using DebugBreakProcess just leaves
			// it unresponsive.
            return GenerateConsoleCtrlEvent( CTRL_C_EVENT, 0 );
        }
 
        // on Windows version < XP we need to find a solution for interrupting the
        // debuggee process
        return false;
#else
        kill( m_debuggeePid, SIGINT );
        return true;
#endif
    } else {
        ::wxMessageBox(_("Can't interrupt debuggee process: I don't know its PID!"), wxT("CodeLite"));
    }
    return false;
}
void DbgGdb::DoCleanup()
{
#ifdef __WXMSW__
    if(GetIsRemoteDebugging()) {
        SetConsoleCtrlHandler((PHANDLER_ROUTINE)SigHandler, FALSE);
        FreeConsole(); // Disconnect any existing console window.
    }
#endif

    wxDELETE(m_gdbProcess);
    SetIsRecording(false);
    m_reverseDebugging = false;
    m_goingDown = false;
    m_attachedMode = false;

    SetIsRemoteDebugging(false);
    SetIsRemoteExtended(false);
    EmptyQueue();
    m_gdbOutputArr.Clear();
    m_bpList.clear();
    m_debuggeeProjectName.Clear();

    // Clear any bufferd output
    m_gdbOutputIncompleteLine.Clear();

    // Free allocated console for this session
    m_consoleFinder.FreeConsole();
}
Esempio n. 3
0
bool DbgGdb::DoInitializeGdb(const std::vector<BreakpointInfo> &bpList, const wxArrayString &cmds)
{
	//place breakpoint at first line
#ifdef __WXMSW__
	ExecuteCmd(wxT("set  new-console on"));
#endif
	ExecuteCmd(wxT("set unwindonsignal on"));

	if (m_info.enablePendingBreakpoints) {
		ExecuteCmd(wxT("set breakpoint pending on"));
	}

	if (m_info.catchThrow) {
		ExecuteCmd(wxT("catch throw"));
	}

#ifdef __WXMSW__
	if (m_info.debugAsserts) {
		ExecuteCmd(wxT("break assert"));
	}
#endif

	ExecuteCmd(wxT("set width 0"));
	ExecuteCmd(wxT("set height 0"));
	ExecuteCmd(wxT("set print pretty on"));  // pretty printing

	// Number of elements to show for arrays (including strings)
	wxString sizeCommand;
	sizeCommand << wxT("set print elements ") << m_info.maxDisplayStringSize;
	ExecuteCmd( sizeCommand );

	// set the project startup commands
	for (size_t i=0; i<cmds.GetCount(); i++) {
		ExecuteCmd(cmds.Item(i));
	}

	// keep the list of breakpoints
	m_bpList = bpList;
	
	if(GetIsRemoteDebugging() == false) 
		// When remote debugging, apply the breakpoints after we connect the 
		// gdbserver
		SetBreakpoints();

	if (m_info.breakAtWinMain) {
		//try also to set breakpoint at WinMain
		WriteCommand(wxT("-break-insert main"), NULL);
	}
	return true;
}
void DbgGdb::GetDebugeePID(const wxString& line)
{
    if(m_debuggeePid == wxNOT_FOUND) {
        if(GetIsRemoteDebugging()) {
            m_debuggeePid = m_gdbProcess->GetPid();

        } else {

            static wxRegEx reDebuggerPidWin(wxT("New Thread ([0-9]+)\\.(0[xX][0-9a-fA-F]+)"));
            static wxRegEx reGroupStarted(wxT("id=\"([0-9]+)\""));
            static wxRegEx reSwitchToThread(wxT("Switching to process ([0-9]+)"));

            // test for the debuggee PID
            // in the line with the following pattern:
            // =thread-group-started,id="i1",pid="15599"
            if(m_debuggeePid < 0 && !line.IsEmpty()) {
                wxString debuggeePidStr;

                if(line.Contains(wxT("=thread-group-started")) && reGroupStarted.Matches(line)) {
                    debuggeePidStr = reGroupStarted.GetMatch(line, 1);

                } else if(line.Contains(wxT("=thread-group-created")) && reGroupStarted.Matches(line)) {
                    debuggeePidStr = reGroupStarted.GetMatch(line, 1);

                } else if(reDebuggerPidWin.Matches(line)) {
                    debuggeePidStr = reDebuggerPidWin.GetMatch(line, 1);

                } else if(reSwitchToThread.Matches(line)) {
                    debuggeePidStr = reSwitchToThread.GetMatch(line, 1);
                }

                if(!debuggeePidStr.IsEmpty()) {
                    long iPid(0);
                    if(debuggeePidStr.ToLong(&iPid)) {
                        m_debuggeePid = iPid;
                        wxString msg;
                        msg << wxT(">> Debuggee process ID: ") << m_debuggeePid;
                        m_observer->UpdateAddLine(msg);

                        // Now there's a known pid, the debugger can be interrupted to let any to-be-disabled bps be
                        // disabled. So...
                        m_observer->DebuggerPidValid();
                    }
                }
            }
        }
    }
}
Esempio n. 5
0
bool DbgGdb::Run(const wxString &args, const wxString &comm)
{
	if ( !GetIsRemoteDebugging() ) {

		// add handler for this command
		return WriteCommand(wxT("-exec-run ") + args, new DbgCmdHandlerAsyncCmd(m_observer));

	} else {
		// attach to the remote gdb server
		wxString cmd;
		//cmd << wxT("-target-select remote ") << comm << wxT(" ") << args;
		cmd << wxT("target remote ") << comm << wxT(" ") << args;
		return WriteCommand(cmd, new DbgCmdHandlerRemoteDebugging(m_observer, this));
		
	}
}
bool DbgGdb::Run(const wxString& args, const wxString& comm)
{
    if(!GetIsRemoteDebugging()) {

        // add handler for this command
        wxString setArgsCommands;
        setArgsCommands << wxT("-exec-arguments ") << args;
        if(!WriteCommand(setArgsCommands, NULL)) return false;

        return WriteCommand(wxT("-exec-run "), new DbgCmdHandlerExecRun(m_observer, this));

    } else {
        // attach to the remote gdb server
        wxString cmd;
        // cmd << wxT("-target-select remote ") << comm << wxT(" ") << args;
        if(GetIsRemoteExtended())
            cmd << wxT("target extended-remote ") << comm << wxT(" ") << args;
        else
            cmd << wxT("target remote ") << comm << wxT(" ") << args;
        return WriteCommand(cmd, new DbgCmdHandlerRemoteDebugging(m_observer, this));
    }
}
Esempio n. 7
0
bool DbgGdb::Start( const DebugSessionInfo& si)
{
    //set the environment variables
    EnvSetter env( m_env, NULL, m_debuggeeProjectName );

    wxString dbgExeName;
    if ( ! DoLocateGdbExecutable( si.debuggerPath, dbgExeName ) ) {
        return false;
    }

    wxString cmd;
#if defined (__WXGTK__) || defined (__WXMAC__)
    cmd << dbgExeName;
    if ( !si.ttyName.IsEmpty() ) {
        cmd << wxT( " --tty=" ) << si.ttyName;
    }
    cmd << wxT( " --interpreter=mi " ) << si.exeName;
#else
    cmd << dbgExeName << wxT( " --interpreter=mi " ) << si.exeName;
#endif

    m_debuggeePid = wxNOT_FOUND;
    m_attachedMode = false;

    m_observer->UpdateAddLine( wxString::Format( wxT( "Current working dir: %s" ), wxGetCwd().c_str() ) );
    m_observer->UpdateAddLine( wxString::Format( wxT( "Launching gdb from : %s" ), si.cwd.c_str() ) );
    m_observer->UpdateAddLine( wxString::Format( wxT( "Starting debugger  : %s" ), cmd.c_str() ) );
#ifdef __WXMSW__
    // When using remote debugging on Windows we need a console window, as this is the only
    // mechanism to send a Ctrl-C event and signal a SIGINT to interrupt the target.
    bool needs_console = GetIsRemoteDebugging() | m_info.showTerminal;
#else
    bool needs_console = m_info.showTerminal;
#endif
    m_gdbProcess = CreateAsyncProcess( this,
                                       cmd,
                                       // show console?
                                       needs_console ? IProcessCreateConsole : IProcessCreateDefault,
                                       si.cwd );
    if ( !m_gdbProcess ) {
        return false;
    }
#ifdef __WXMSW__
    if ( GetIsRemoteDebugging() ) {
        // This doesn't really make sense, but AttachConsole fails without it...
        AllocConsole();
        FreeConsole(); // Disconnect any existing console window.

        if ( !AttachConsole( m_gdbProcess->GetPid() ) )
            m_observer->UpdateAddLine( wxString::Format(wxT("AttachConsole returned error %d"), GetLastError()));

        // We can at least make the window invisible if the user doesn't want to see it.
        if ( !m_info.showTerminal )
            SetWindowPos(GetConsoleWindow(), HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDEWINDOW);

        // Finally we ignore SIGINT so we don't get killed by our own signal
        signal(SIGINT, SIG_IGN);
    }
#endif
    m_gdbProcess->SetHardKill( true );
    DoInitializeGdb( si );
    return true;
}
Esempio n. 8
0
// Initialization stage
bool DbgGdb::DoInitializeGdb(const DebugSessionInfo& sessionInfo)
{
    m_goingDown = false;
    m_internalBpId = wxNOT_FOUND;
#ifdef __WXMSW__
    ExecuteCmd( wxT( "set  new-console on" ) );
#endif
    ExecuteCmd( wxT( "set unwindonsignal on" ) );

    wxString breakinsertcmd(wxT("-break-insert "));

    if ( m_info.enablePendingBreakpoints ) {
        ExecuteCmd( wxT( "set breakpoint pending on" ) );
        breakinsertcmd << wxT("-f ");
    }

    if ( m_info.catchThrow ) {
        ExecuteCmd( wxT( "catch throw" ) );
    }

#ifdef __WXMSW__
    if ( m_info.debugAsserts ) {
        ExecuteCmd( wxT( "break assert" ) );
    }
#endif

    ExecuteCmd( wxT( "set width 0" ) );
    ExecuteCmd( wxT( "set height 0" ) );

    // Number of elements to show for arrays (including strings)
    wxString sizeCommand;
    sizeCommand << wxT( "set print elements " ) << m_info.maxDisplayStringSize;
    ExecuteCmd( sizeCommand );

    // set the project startup commands
    for ( size_t i=0; i<sessionInfo.cmds.GetCount(); i++ ) {
        ExecuteCmd( sessionInfo.cmds.Item( i ) );
    }

    // keep the list of breakpoints
    m_bpList = sessionInfo.bpList;


    bool setBreakpointsAfterMain( m_info.applyBreakpointsAfterProgramStarted );
    if( GetIsRemoteDebugging() == false && !setBreakpointsAfterMain ) {
        // When remote debugging, apply the breakpoints after we connect the
        // gdbserver
        SetBreakpoints();

    } else if( setBreakpointsAfterMain && m_bpList.empty() == false ) {
        // Place an 'internal' breakpoint at main. Once this breakpoint is hit
        // set all breakpoints and remove the 'internal' one.
        // Then 'continue', unless the user has said he actually _wants_ to break at main
        WriteCommand( breakinsertcmd + wxT("-t main"), new DbgFindMainBreakpointIdHandler( m_observer, this ) );
    }

    if (m_info.breakAtWinMain) {
        // Set a breakpoint at WinMain
        // Use a temporary one, so that it isn't duplicated in future sessions
        WriteCommand( breakinsertcmd + wxT("-t main"), NULL );
        // Flag that we've done this. DbgFindMainBreakpointIdHandler::ProcessOutput uses this
        // to decide whether or not to 'continue' after setting BPs after main()
        SetShouldBreakAtMain(true);
    } else {
        SetShouldBreakAtMain(false); // Needs explicitly to be set, in case the user has just changed his options
    }

    // Enable python based pretty printing?
    if ( sessionInfo.enablePrettyPrinting ) {
        WriteCommand( wxT( "-enable-pretty-printing" ), NULL );
    }

    // Add the additional search paths
    for(size_t i=0; i<sessionInfo.searchPaths.GetCount(); ++i) {
        wxString dirCmd;
        wxString path = sessionInfo.searchPaths.Item(i);
        path.Trim().Trim(false);
        if ( path.Contains(" ") ) {
            path.Prepend('"').Append('"');
        }
        dirCmd << "-environment-directory " << path;
        WriteCommand( dirCmd, NULL );
    }
    return true;
}
Esempio n. 9
0
void DbgGdb::Poke()
{
	static wxRegEx reCommand(wxT("^([0-9]{8})"));

	//poll the debugger output
	wxString line;
	if ( !m_gdbProcess || m_gdbOutputArr.IsEmpty() ) {
		return;
	}

	if (m_debuggeePid == wxNOT_FOUND) {
		if (GetIsRemoteDebugging()) {
			m_debuggeePid = m_gdbProcess->GetPid();
			
		} else {
			std::vector<long> children;
			ProcUtils::GetChildren(m_gdbProcess->GetPid(), children);
			std::sort(children.begin(), children.end());
			if (children.empty() == false) {
				m_debuggeePid = children.at(0);
			}

			if (m_debuggeePid != wxNOT_FOUND) {
				wxString msg;
				msg << wxT("Debuggee process ID: ") << m_debuggeePid;
				m_observer->UpdateAddLine(msg);
			}
		}
	}

	while ( DoGetNextLine( line ) ) {

		// For string manipulations without damaging the original line read
		wxString tmpline ( line );
		StripString( tmpline );
		tmpline.Trim().Trim(false);

		if (m_info.enableDebugLog) {
			//Is logging enabled?

			if (line.IsEmpty() == false && !tmpline.StartsWith(wxT(">")) ) {
				wxString strdebug(wxT("DEBUG>>"));
				strdebug << line;
				m_observer->UpdateAddLine(strdebug);
			}
		}

		if (reConnectionRefused.Matches(line)) {
			StripString(line);
#ifdef __WXGTK__
			m_consoleFinder.FreeConsole();
#endif
			m_observer->UpdateAddLine(line);
			m_observer->UpdateGotControl(DBG_EXITED_NORMALLY);
			return;
		}

		if( tmpline.StartsWith(wxT(">")) ) {
			// Shell line, probably user command line
			continue;
		}

		if (line.StartsWith(wxT("~")) || line.StartsWith(wxT("&"))) {

			// lines starting with ~ are considered "console stream" message
			// and are important to the CLI handler
			bool consoleStream(false);
			if ( line.StartsWith(wxT("~")) ) {
				consoleStream = true;
			}

			// Filter out some gdb error lines...
			if (FilterMessage(line)) {
				continue;
			}

			StripString( line );

			// If we got a valid "CLI Handler" instead of writing the output to
			// the output view, concatenate it into the handler buffer
			if ( GetCliHandler() && consoleStream ) {
				GetCliHandler()->Append( line );
			} else if ( consoleStream ) {
				// log message
				m_observer->UpdateAddLine( line );
			}
		} else if (reCommand.Matches(line)) {

			//not a gdb message, get the command associated with the message
			wxString id = reCommand.GetMatch(line, 1);

			if ( GetCliHandler() && GetCliHandler()->GetCommandId() == id ) {
				// probably the "^done" message of the CLI command
				GetCliHandler()->ProcessOutput( line );
				SetCliHandler( NULL ); // we are done processing the CLI

			} else {
				//strip the id from the line
				line = line.Mid(8);
				DoProcessAsyncCommand(line, id);

			}
		} else if (line.StartsWith(wxT("^done")) || line.StartsWith(wxT("*stopped"))) {
			//Unregistered command, use the default AsyncCommand handler to process the line
			DbgCmdHandlerAsyncCmd cmd(m_observer);
			cmd.ProcessOutput(line);
		} else {
			//Unknow format, just log it
			if( m_info.enableDebugLog && !FilterMessage(line)) {
				m_observer->UpdateAddLine(line);
			}
		}
	}
}