public int Terminate() { OutputText("Debugger terminating."); try { mHost.Stop(); OutputText("Debugger terminated."); return(VSConstants.S_OK); } catch (ApplicationException) { OutputText("Failed to stop debugger!"); OutputText("\r\n"); OutputText("You need to install the VMWare VIX API!"); AD7Util.MessageBox("Failed to stop debugger! You need to install the VMWare VIX API!", "Information"); } catch (Exception ex) { OutputText("Failed to stop debugger! Exception message: " + ex.Message); OutputText("\r\n"); OutputText("You probably need to install the VMWare VIX API!"); AD7Util.MessageBox( "Failed to stop debugger! You probably need to install the VMWare VIX API!\r\n\r\nCheck Output window for more details.", "Information"); } return(VSConstants.E_FAIL); }
protected void LaunchGdbClient() { OutputText("Launching GDB client."); if (File.Exists(Cosmos.Build.Common.CosmosPaths.GdbClientExe)) { var xPSInfo = new ProcessStartInfo(Cosmos.Build.Common.CosmosPaths.GdbClientExe); xPSInfo.Arguments = "\"" + Path.ChangeExtension(mProjectFile, ".cgdb") + "\"" + @" /Connect"; xPSInfo.UseShellExecute = false; xPSInfo.RedirectStandardInput = false; xPSInfo.RedirectStandardError = false; xPSInfo.RedirectStandardOutput = false; xPSInfo.CreateNoWindow = false; Process.Start(xPSInfo); } else { AD7Util.MessageBox(string.Format( "The GDB-Client could not be found at \"{0}\". Please deactivate it under \"Properties/Debug/Enable GDB\"", Cosmos.Build.Common.CosmosPaths.GdbClientExe), "GDB-Client"); } }
public AD7StackFrame(AD7Engine aEngine, AD7Thread aThread, AD7Process aProcess) { mEngine = aEngine; mThread = aThread; mProcess = aProcess; var xProcess = mEngine.mProcess; if (mHasSource = xProcess.mCurrentAddress.HasValue) { var xAddress = xProcess.mCurrentAddress.Value; var xSourceInfos = xProcess.mDebugInfoDb.GetSourceInfos(xAddress); if (!xSourceInfos.ContainsKey(xAddress)) { //Attempt to find the ASM address of the first ASM line of the C# line that contains //the current ASM address line // Because of Asm breakpoints the address we have might be in the middle of a C# line. // So we find the closest address to ours that is less or equal to ours. var xQry = from x in xSourceInfos where x.Key <= xAddress orderby x.Key descending select x.Key; if (xQry.Count() > 0) { xAddress = xQry.First(); } } if (mHasSource = xSourceInfos.ContainsKey(xAddress)) { var xSourceInfo = xSourceInfos[xAddress]; mDocName = xSourceInfo.SourceFile; mFunctionName = xSourceInfo.MethodName; mLineNum = (uint)xSourceInfo.LineStart; // Multiple labels that point to a single address can happen because of exception handling exits etc. // Because of this given an address, we might find more than one label that matches the address. // Currently, the label we are looking for will always be the first one so we choose that one. // In the future this might "break", so be careful about this. In the future we may need to classify // labels in the output and mark them somehow. var xLabelsForAddr = xProcess.mDebugInfoDb.GetLabels(xAddress); if (xLabelsForAddr.Length > 0) { MethodIlOp xSymbolInfo; string xLabel = xLabelsForAddr[0]; // Necessary for LINQ xSymbolInfo = aProcess.mDebugInfoDb.TryGetFirstMethodIlOpByLabelName(xLabel); if (xSymbolInfo != null) { var xMethod = mProcess.mDebugInfoDb.GetMethod(xSymbolInfo.MethodID.Value); var xAllInfos = aProcess.mDebugInfoDb.GetAllLocalsAndArgumentsInfosByMethodLabelName(xMethod.LabelCall); mLocalInfos = xAllInfos.Where(q => !q.IsArgument).ToArray(); mArgumentInfos = xAllInfos.Where(q => q.IsArgument).ToArray(); if (mArgumentInfos.Length > 0) { mParams = new DebugLocalInfo[mArgumentInfos.Length]; for (int i = 0; i < mArgumentInfos.Length; i++) { mParams[i] = new DebugLocalInfo { Name = mArgumentInfos[i].NAME, Index = i, IsLocal = false }; } mParams = mParams.OrderBy(i => i.Name, StringComparer.OrdinalIgnoreCase).ToArray(); } if (mLocalInfos.Length > 0) { mLocals = new DebugLocalInfo[mLocalInfos.Length]; for (int i = 0; i < mLocalInfos.Length; i++) { mLocals[i] = new DebugLocalInfo { Name = mLocalInfos[i].NAME, Index = i, IsLocal = true }; } mLocals = mLocals.OrderBy(i => i.Name, StringComparer.OrdinalIgnoreCase).ToArray(); } } } else { AD7Util.ShowError("No Symbol found for address 0x" + xAddress.ToString("X8").ToUpper()); } xProcess.DebugMsg(String.Format("StackFrame: Returning: {0}#{1}[{2}]", mDocName, mFunctionName, mLineNum)); } } if (!mHasSource) { xProcess.DebugMsg("StackFrame: No Source available"); } // If source information is available, create the collections of locals and parameters and populate them with // values from the debuggee. //if (m_hasSource) { //if (mArgumentInfos.Length > 0) { //m_parameters = new VariableInformation[m_numParameters]; //m_engine.DebuggedProcess.GetFunctionArgumentsByIP(m_threadContext.eip, m_threadContext.ebp, m_parameters); //} //if (mLocalInfos.Length > 0) { //m_locals = new VariableInformation[m_numLocals]; //m_engine.DebuggedProcess.GetFunctionLocalsByIP(m_threadContext.eip, m_threadContext.ebp, m_locals); //} //} }
internal void Step(enum_STEPKIND aKind) { if (aKind == enum_STEPKIND.STEP_INTO) { // F11 mStepping = true; if (ASMSteppingMode) { mDbgConnector.SendCmd(Vs2Ds.AsmStepInto); mDbgConnector.SendRegisters(); } else { SetINT3sOnCurrentMethod(); mDbgConnector.SendCmd(Vs2Ds.StepInto); } } else if (aKind == enum_STEPKIND.STEP_OVER) { // F10 mStepping = true; if (ASMSteppingMode) { ASMStepOver(); } else { SetINT3sOnCurrentMethod(); mDbgConnector.SendCmd(Vs2Ds.StepOver); } } else if (aKind == enum_STEPKIND.STEP_OUT) { // Shift-F11 ClearINT3sOnCurrentMethod(); mStepping = true; if (ASMSteppingMode) { mASMSteppingOut = true; mASMSteppingOut_NumEndMethodLabelsPassed = 0; mDbgConnector.SendCmd(Vs2Ds.AsmStepInto); //Set a condition to say we should be doing step out //On break, check line just stepped. //If current line is RET - do one more step then break. //Else do another step } else { mDbgConnector.SendCmd(Vs2Ds.StepOut); } } else if (aKind == enum_STEPKIND.STEP_BACKWARDS) { // STEP_BACKWARDS - Supported at all by VS? // // Possibly, by dragging the execution location up // or down through the source code? -Orvid AD7Util.MessageBox("Step backwards is not supported."); mCallback.OnStepComplete(); // Have to call this otherwise VS gets "stuck" } else { AD7Util.MessageBox("Unknown step type requested."); mCallback.OnStepComplete(); // Have to call this otherwise VS gets "stuck" } }
void DbgCmdKernelPanic(uint nr) { AD7Util.MessageBox("Kernel panic: 0x" + nr.ToString()); }
internal AD7Process(Dictionary <string, string> 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 PipeClient(Pipes.DownName); mDebugUpPipe = new 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: #region CheckIfHyperVServiceIsRunning using (System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController("vmms")) { try { if (sc.Status == System.ServiceProcess.ServiceControllerStatus.Running) { AD7Util.MessageBox( "The Hyper-V Virtual Machine Management Service will be stopped. This is needed to allow to run VMware. If you press \"No\" the debug will stop.", "Question"); sc.Stop(); } } catch (InvalidOperationException) { // service not present } } #endregion CheckIfHyperVServiceIsRunning mHost = new VMware(mDebugInfo, xUseGDB); break; #if SERIAL_PORT case LaunchType.Slave: mHost = new Slave(mDebugInfo, xUseGDB); break; #endif 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(Resources.BochsIsNotInstalled); } string bochsConfigurationFileName; mDebugInfo.TryGetValue(BuildProperties.BochsEmulatorConfigurationFileString, out bochsConfigurationFileName); 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 Bochs(mDebugInfo, xUseGDB, bochsConfigurationFile); //((Host.Bochs)mHost).FixBochsConfiguration(new KeyValuePair<string, string>[] { new KeyValuePair<string, string>("IsoFileName", mISO) }); break; case LaunchType.IntelEdison: mHost = new IntelEdison(mDebugInfo, false); break; case LaunchType.HyperV: mHost = new HyperV(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(); } }
private void DbgCmdMessageBox(string message) { AD7Util.MessageBox("Message from your Cosmos operating system:\r\n\r\n" + message); }
private void DbgCmdNullReferenceOccurred(uint lastEIPAddress) { AD7Util.MessageBox(String.Format("NullReferenceException occurred at address 0x{0:X8}! Halting now.", lastEIPAddress)); }
private void DbgCmdStackOverflowOccurred(uint lastEIPAddress) { AD7Util.MessageBox(String.Format("Stack overflow occurred at address 0x{0:X8}! Halting now.", lastEIPAddress)); }
private void DbgCmdStackCorruptionOccurred(uint lastEIPAddress) { AD7Util.MessageBox(String.Format("Stack corruption occurred at address 0x{0:X8}! Halting now.", lastEIPAddress)); }
public void SendAssembly(bool noDisplay = false) { AD7Util.Log("SendAssembly"); ASMWindow_CurrentLineUpdated.Reset(); ASMWindow_NextAddress1Updated.Reset(); ASMWindow_NextLine1Updated.Reset(); uint xAddress = mCurrentAddress.Value; var xSourceInfos = mDebugInfoDb.GetSourceInfos(xAddress); AD7Util.Log("SendAssembly - SourceInfos retrieved for address 0x{0}", xAddress.ToString("X8")); if (xSourceInfos.Count > 0) { //We should be able to display the asesembler source for any address regardless of whether a C# //line is associated with it. //However, we do not store all labels in the debug database because that would make the compile //time insane. //So: // - We take the current address amd find the method it is part of // - We use the method header label as a start point and find all asm labels till the method footer label // - We then find all the asm for these labels and display it. Label[] xLabels = mDebugInfoDb.GetMethodLabels(xAddress); AD7Util.Log("SendAssembly - MethodLabels retrieved"); // get the label of our current position, or the closest one before var curPosLabel = xLabels.Where(i => i.Address <= xAddress).OrderByDescending(i => i.Address).FirstOrDefault(); // if curPosLabel is null, grab the first one. if (curPosLabel == null) { curPosLabel = xLabels[0]; } var curPosIndex = Array.IndexOf(xLabels, curPosLabel); // we want 50 items before and after the current item, so 100 in total. var itemsBefore = 10; var itemsAfter = 10; if (curPosIndex < itemsBefore) { // there are no 50 items before the current one, so adjust itemsBefore = curPosIndex; } if ((curPosIndex + itemsAfter) >= xLabels.Length) { // there are no 50 items after the current one, so adjust itemsAfter = xLabels.Length - curPosIndex; } var newArr = new Label[itemsBefore + itemsAfter]; for (int i = 0; i < newArr.Length; i++) { newArr[i] = xLabels[(curPosIndex - itemsBefore) + i]; } xLabels = newArr; //The ":" has to be added in because labels in asm code have it on the end - it's easier to add it here than //strip them out of the read asm var xLabelNames = xLabels.Select(x => x.Name + ":").ToList(); // Get assembly source var xCode = AsmSource.GetSourceForLabels(Path.ChangeExtension(mISO, ".asm"), xLabelNames); AD7Util.Log("SendAssembly - SourceForLabels retrieved"); // Get label for current address. // A single address can have multiple labels (IL, Asm). Because of this we search // for the one with the Asm tag. We dont have the tags in this debug info though, // so instead if there is more than one label we use the longest one which is the Asm tag. string xCurrentLabel = ""; var xCurrentLabels = mDebugInfoDb.GetLabels(xAddress); if (xCurrentLabels.Length > 0) { xCurrentLabel = xCurrentLabels.OrderBy(q => q.Length).Last(); } if (string.IsNullOrEmpty(xCurrentLabel)) { xCurrentLabel = "NO_METHOD_LABEL_FOUND"; } // Insert filter labels list as THIRD(!) line of our data stream string filterLabelsList = ""; foreach (var addressInfo in INT3sSet) { //"We have to add the ".00:" because of how the ASM window works... filterLabelsList += "|" + addressInfo.Value + ".00"; } if (filterLabelsList.Length > 0) { filterLabelsList = filterLabelsList.Substring(1); } xCode.Insert(0, filterLabelsList + "\r\n"); // Insert parameters as SECOND(!) line of our data stream xCode.Insert(0, (noDisplay ? "NoDisplay" : "") + "|" + (ASMSteppingMode ? "AsmStepMode" : "") + "\r\n"); // Insert current line's label as FIRST(!) line of our data stream xCode.Insert(0, xCurrentLabel + "\r\n"); //THINK ABOUT THE ORDER that he above lines occur in and where they insert data into the stream - don't switch it! AD7Util.Log("SendAssembly - Sending through pipe now"); mDebugDownPipe.SendCommand(Debugger2Windows.AssemblySource, Encoding.UTF8.GetBytes(xCode.ToString())); AD7Util.Log("SendAssembly - Done"); } }