int IDebugEngine2.ContinueFromSynchronousEvent(IDebugEvent2 aEvent) { // Called by the SDM to indicate that a synchronous debug event, previously sent by the DE to the SDM, // was received and processed. The only event the engine sends in this fashion is Program Destroy. // It responds to that event by shutting down the engine. // // This is used in some cases - I set a BP here and it does get hit sometime during breakpoints // being triggered for example. try { if (aEvent is AD7ProgramDestroyEvent) { mEngineCallback = null; mProgramID = Guid.Empty; mThread = null; mProgNode = null; } else { System.Diagnostics.Debug.Fail("Unknown synchronious event"); } } catch (Exception e) { return(EngineUtils.UnexpectedException(e)); } return(VSConstants.S_OK); }
// During startup these methods are called in this order: // -LaunchSuspended // -ResumeProcess // -Attach - Triggered by Attach int IDebugEngineLaunch2.LaunchSuspended(string aPszServer, IDebugPort2 aPort, string aDebugInfo , string aArgs, string aDir, string aEnv, string aOptions, enum_LAUNCH_FLAGS aLaunchFlags , uint aStdInputHandle, uint aStdOutputHandle, uint hStdError, IDebugEventCallback2 aAD7Callback , out IDebugProcess2 oProcess) { // Launches a process by means of the debug engine. // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language), // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state. oProcess = null; try { mEngineCallback = new EngineCallback(this, aAD7Callback); var xDebugInfo = new NameValueCollection(); NameValueCollectionHelper.LoadFromString(xDebugInfo, aDebugInfo); //TODO: In the future we might support command line args for kernel etc //string xCmdLine = EngineUtils.BuildCommandLine(exe, args); //var processLaunchInfo = new ProcessLaunchInfo(exe, xCmdLine, dir, env, options, launchFlags, hStdInput, hStdOutput, hStdError); AD7EngineCreateEvent.Send(this); oProcess = mProcess = new AD7Process(xDebugInfo, mEngineCallback, this, aPort); // We only support one process, so just use its ID for the program ID mProgramID = mProcess.ID; //AD7ThreadCreateEvent.Send(this, xProcess.Thread); mModule = new AD7Module(); mProgNode = new AD7ProgramNode(mProcess.PhysID); } catch (NotSupportedException) { return(VSConstants.S_FALSE); } catch (Exception e) { return(EngineUtils.UnexpectedException(e)); } return(VSConstants.S_OK); }
internal AD7Process(NameValueCollection aDebugInfo, EngineCallback aCallback, AD7Engine aEngine, IDebugPort2 aPort) { mCallback = aCallback; mDebugInfo = aDebugInfo; mLaunch = (LaunchType)Enum.Parse(typeof(LaunchType), aDebugInfo[BuildPropertyNames.LaunchString]); if (mDebugDownPipe == null) { mDebugDownPipe = new Cosmos.Debug.Common.PipeClient(Pipes.DownName); mDebugUpPipe = new Cosmos.Debug.Common.PipeServer(Pipes.UpName); mDebugUpPipe.DataPacketReceived += mDebugUpPipe_DataPacketReceived; mDebugUpPipe.Start(); } else { mDebugUpPipe.CleanHandlers(); mDebugUpPipe.DataPacketReceived += mDebugUpPipe_DataPacketReceived; } // Must be after mDebugDownPipe is initialized OutputClear(); OutputText("Debugger process initialized."); mISO = mDebugInfo["ISOFile"]; OutputText("Using ISO file " + mISO + "."); mProjectFile = mDebugInfo["ProjectFile"]; // bool xUseGDB = string.Equals(mDebugInfo[BuildPropertyNames.EnableGDBString], "true", StringComparison.InvariantCultureIgnoreCase); OutputText("GDB " + (xUseGDB ? "Enabled" : "Disabled") + "."); // var xGDBClient = false; Boolean.TryParse(mDebugInfo[BuildPropertyNames.StartCosmosGDBString], out xGDBClient); switch (mLaunch) { case LaunchType.VMware: mHost = new Host.VMware(mDebugInfo, xUseGDB); break; case LaunchType.Slave: mHost = new Host.Slave(mDebugInfo, xUseGDB); break; case LaunchType.Bochs: // The project has been created on another machine or Bochs has been uninstalled since the project has // been created. if (!BochsSupport.BochsEnabled) { throw new Exception(ResourceStrings.BochsIsNotInstalled); } string bochsConfigurationFileName = mDebugInfo[BuildProperties.BochsEmulatorConfigurationFileString]; if (string.IsNullOrEmpty(bochsConfigurationFileName)) { bochsConfigurationFileName = BuildProperties.BochsDefaultConfigurationFileName; } if (!Path.IsPathRooted(bochsConfigurationFileName)) { // Assume the configuration file name is relative to project output path. bochsConfigurationFileName = Path.Combine(new FileInfo(mDebugInfo["ProjectFile"]).Directory.FullName, mDebugInfo["OutputPath"], bochsConfigurationFileName); } FileInfo bochsConfigurationFile = new FileInfo(bochsConfigurationFileName); // TODO : What if the configuration file doesn't exist ? This will throw a FileNotFoundException in // the Bochs class constructor. Is this appropriate behavior ? mHost = new Host.Bochs(mDebugInfo, xUseGDB, bochsConfigurationFile); //((Host.Bochs)mHost).FixBochsConfiguration(new KeyValuePair<string, string>[] { new KeyValuePair<string, string>("IsoFileName", mISO) }); break; case LaunchType.IntelEdison: mHost = new Host.IntelEdison(mDebugInfo, false); break; default: throw new Exception("Invalid Launch value: '" + mLaunch + "'."); } mHost.OnShutDown += HostShutdown; string xDbPath = Path.ChangeExtension(mISO, "cdb"); if (!File.Exists(xDbPath)) { throw new Exception("Debug data file " + xDbPath + " not found. Could be a omitted build process of Cosmos project so that not created."); } mDebugInfoDb = new DebugInfo(xDbPath); mDebugInfoDb.LoadLookups(); CreateDebugConnector(); aEngine.BPMgr.SetDebugConnector(mDbgConnector); mEngine = aEngine; mThread = new AD7Thread(aEngine, this); mCallback.OnThreadStart(mThread); mPort = aPort; if (xUseGDB && xGDBClient) { LaunchGdbClient(); } }