//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public CLangDebuggeeModule (DebugEngine engine, MiAsyncRecord asyncRecord) : base (engine) { try { if (asyncRecord == null) { throw new ArgumentNullException ("asyncRecord"); } Name = asyncRecord ["id"] [0].GetString (); RemotePath = asyncRecord ["target-name"] [0].GetString (); RemoteLoadAddress = 0; SymbolsPath = asyncRecord ["host-name"] [0].GetString (); // // The 'symbols-loaded' field is emitted only for backward compatibility and should not be relied on to convey any useful information. // if ((!string.IsNullOrEmpty (SymbolsPath)) && File.Exists (SymbolsPath)) { SymbolsLoaded = true; } } catch (Exception e) { LoggingUtils.HandleException (e); throw; } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeExpression (DebugEngine engine, DebuggeeStackFrame stackFrame, string expression, uint radix) { m_debugEngine = engine; m_stackFrame = stackFrame; m_expression = expression; m_radix = radix; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeDocumentContext (DebugEngine engine, string fileName, TEXT_POSITION beginPosition, TEXT_POSITION endPosition) { m_engine = engine; m_fileName = PathUtils.ConvertPathCygwinToWindows (fileName); m_beginPosition = beginPosition; m_endPosition = endPosition; m_codeContext = null; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebugEngineCallback (DebugEngine engine, IDebugEventCallback2 ad7EventCallback) { Engine = engine; m_ad7EventCallback = ad7EventCallback; m_cLangEventCallback = new CLangDebuggerCallback (engine); m_javaLangEventCallback = new JavaLangDebuggerCallback (engine); // // Register function handlers for specific events. // m_debuggerCallback = new Dictionary<Guid, DebuggerEventDelegate> (); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.BreakpointHit)), OnBreakpoint); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.BreakpointBound)), OnBreakpointBound); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.BreakpointError)), OnBreakpointError); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.Error)), OnError); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.Exception)), OnException); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.LoadComplete)), OnLoadComplete); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.ModuleLoad)), OnModuleLoad); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.OutputString)), OnOutputString); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.ProcessCreate)), OnProgramCreate); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.ProgramDestroy)), OnProgramDestroy); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.StepComplete)), OnStepComplete); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.SymbolSearch)), OnSymbolSearch); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.ThreadCreate)), OnThreadCreate); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (DebugEngineEvent.ThreadDestroy)), OnThreadDestroy); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public JavaLangDebugger (DebugEngine debugEngine, DebuggeeProgram debugProgram) { Engine = debugEngine; m_javaLangCallback = new JavaLangDebuggerCallback (debugEngine); JavaProgram = new JavaLangDebuggeeProgram (this, debugProgram); m_jdbSetup = new JdbSetup (debugProgram.DebugProcess.NativeProcess); Engine.Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format ("Configuring JDB for {0}:{1}...", m_jdbSetup.Host, m_jdbSetup.Port)), null, null); JdbClient = new JdbClient (m_jdbSetup); JdbClient.OnAsyncStdout = OnClientAsyncOutput; JdbClient.OnAsyncStderr = OnClientAsyncOutput; JdbClient.Start (); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public JavaLangDebuggerCallback (DebugEngine engine) { m_debugEngine = engine; // // Register function handlers for specific events. // m_debuggerCallback = new Dictionary<Guid, JavaLangDebuggerEventDelegate> (); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (JavaLangDebuggerEvent.AttachClient)), OnAttachClient); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (JavaLangDebuggerEvent.DetachClient)), OnDetachClient); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (JavaLangDebuggerEvent.StopClient)), OnStopClient); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (JavaLangDebuggerEvent.ContinueClient)), OnContinueClient); m_debuggerCallback.Add (ComUtils.GuidOf (typeof (JavaLangDebuggerEvent.TerminateClient)), OnTerminateClient); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebugBreakpointManager (DebugEngine engine) { Engine = engine; m_pendingBreakpoints = new List<DebuggeeBreakpointPending> (); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public CLangDebugger (DebugEngine debugEngine, LaunchConfiguration launchConfiguration, DebuggeeProgram debugProgram) { Engine = debugEngine; m_launchConfiguration = launchConfiguration; NativeProgram = new CLangDebuggeeProgram (this, debugProgram); NativeMemoryBytes = new CLangDebuggeeMemoryBytes (this); VariableManager = new CLangDebuggerVariableManager (this); // // Evaluate target device's architecture triple. // string preferedGdbAbiToolPrefix = string.Empty; bool allow64BitAbis = true; switch (debugProgram.DebugProcess.NativeProcess.PrimaryCpuAbi) { case "armeabi": case "armeabi-v7a": { preferedGdbAbiToolPrefix = "arm-linux-androideabi"; break; } case "arm64-v8a": { if (allow64BitAbis) { preferedGdbAbiToolPrefix = "aarch64-linux-android"; } else { preferedGdbAbiToolPrefix = "arm-linux-androideabi"; } break; } case "x86": { preferedGdbAbiToolPrefix = "i686-linux-android"; break; } case "x86_64": { if (allow64BitAbis) { preferedGdbAbiToolPrefix = "x86_64-linux-android"; } else { preferedGdbAbiToolPrefix = "i686-linux-android"; } break; } case "mips": { preferedGdbAbiToolPrefix = "mipsel-linux-android"; break; } case "mips64": { if (allow64BitAbis) { preferedGdbAbiToolPrefix = "mips64el-linux-android"; } else { preferedGdbAbiToolPrefix = "mipsel-linux-android"; } break; } } if (string.IsNullOrEmpty (preferedGdbAbiToolPrefix)) { throw new InvalidOperationException (string.Format ("Unrecognised target primary CPU ABI: {0}", debugProgram.DebugProcess.NativeProcess.PrimaryCpuAbi)); } bool preferedGdbAbiIs64Bit = preferedGdbAbiToolPrefix.Contains ("64"); Engine.Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format ("Configuring GDB for '{0}' target...", preferedGdbAbiToolPrefix)), null, null); // // Android++ bundles its own copies of GDB to get round various NDK issues. Search for these. // string androidPlusPlusRoot = Environment.GetEnvironmentVariable ("ANDROID_PLUS_PLUS"); // // Build GDB version permutations. // List<string> gdbToolPermutations = new List<string> (); string [] availableHostArchitectures = new string [] { "x86", "x86_64" }; foreach (string arch in availableHostArchitectures) { if (arch.Contains ("64") && !Environment.Is64BitOperatingSystem) { continue; } string gdbToolFilePattern = string.Format ("{0}-gdb.cmd", preferedGdbAbiToolPrefix); string [] availableVersionPaths = Directory.GetDirectories (Path.Combine (androidPlusPlusRoot, "contrib", "gdb", "bin", arch), "*.*.*", SearchOption.TopDirectoryOnly); foreach (string versionPath in availableVersionPaths) { string [] gdbToolMatches = Directory.GetFiles (versionPath, gdbToolFilePattern, SearchOption.TopDirectoryOnly); foreach (string tool in gdbToolMatches) { gdbToolPermutations.Add (tool); } } } if (gdbToolPermutations.Count == 0) { throw new InvalidOperationException ("Could not locate required 32/64-bit GDB deployments."); } else { // // Pick the oldest GDB version available if running 'Jelly Bean' or below. // bool forceNdkR9dClient = (debugProgram.DebugProcess.NativeProcess.HostDevice.SdkVersion <= AndroidSettings.VersionCode.JELLY_BEAN); if (forceNdkR9dClient) { m_gdbSetup = new GdbSetup (debugProgram.DebugProcess.NativeProcess, gdbToolPermutations [0]); } else { m_gdbSetup = new GdbSetup (debugProgram.DebugProcess.NativeProcess, gdbToolPermutations [gdbToolPermutations.Count - 1]); } // // A symbolic link to 'share' is placed in the architecture directory, provide GDB with that location. // string architecturePath = Path.GetDirectoryName (Path.GetDirectoryName (m_gdbSetup.GdbToolPath)); string pythonGdbScriptsPath = Path.Combine (architecturePath, "share", "gdb"); m_gdbSetup.GdbToolArguments += " --data-directory " + PathUtils.SantiseWindowsPath (pythonGdbScriptsPath); } if (m_gdbSetup == null) { throw new InvalidOperationException ("Could not evaluate a suitable GDB instance. Ensure you have the correct NDK deployment for your system's architecture."); } if (m_launchConfiguration != null) { string launchDirectory; if (m_launchConfiguration.TryGetValue ("LaunchSuspendedDir", out launchDirectory)) { m_gdbSetup.SymbolDirectories.Add (launchDirectory); } } GdbServer = new GdbServer (m_gdbSetup); GdbClient = new GdbClient (m_gdbSetup); GdbClient.OnResultRecord = OnClientResultRecord; GdbClient.OnAsyncRecord = OnClientAsyncRecord; GdbClient.OnStreamRecord = OnClientStreamRecord; GdbClient.Start (); }