Beispiel #1
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        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 ();
    }
Beispiel #3
0
        //private int m_interruptOperationCounter = 0;

        //private ManualResetEvent m_interruptOperationCompleted = null;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        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();
        }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    #region IDebugEngine2 Members

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public int Attach (IDebugProgram2 [] rgpPrograms, IDebugProgramNode2 [] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason)
    {
      // 
      // Attach the debug engine to a program.
      // 

      LoggingUtils.PrintFunction ();

      m_sdmCallback = new DebugEngineCallback (this, ad7Callback);

      m_cLangCallback = new CLangDebuggerCallback (this);

      m_javaLangCallback = new JavaLangDebuggerCallback (this);

      try
      {
        if ((rgpPrograms == null) || (rgpPrograms.Length == 0))
        {
          throw new ApplicationException ("Attach failed. No target process specified.");
        }

        if (celtPrograms > 1)
        {
          throw new ApplicationException ("Attach failed. Can not debug multiple target processes concurrently.");
        }

        if (Program != null)
        {
          throw new ApplicationException ("Attach failed. Already attached to " + Program.DebugProcess.NativeProcess.Name);
        }

        AndroidAdb.Refresh ();

        Program = rgpPrograms [0] as DebuggeeProgram;

        Program.AttachedEngine = this;

        Program.DebugProcess.NativeProcess.RefreshPackageInfo ();

        Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format ("Starting GDB client...")), null, null);

        NativeDebugger = new CLangDebugger (this, m_launchConfiguration, Program);

        Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format ("Starting JDB client...")), null, null);

        JavaDebugger = new JavaLangDebugger (this, Program);

        ThreadPool.QueueUserWorkItem (delegate (object obj)
        {
          // 
          // When this method is called, the DE needs to send these events in sequence:
          // 1. IDebugEngineCreate2
          // 2. IDebugProgramCreateEvent2
          // 3. IDebugLoadCompleteEvent2
          // 4. (if enum_ATTACH_REASON.ATTACH_REASON_LAUNCH), IDebugEntryPointEvent2
          // 

          try
          {
            Broadcast (new DebugEngineEvent.EngineCreate (this), Program, null);

            // 
            // Run a couple of tests which prevent the run-as tool from functioning properly:
            // 
            // 1) Test if this device/emulator is susceptible to a (usually 4.3 specific) run-as permissions bug.
            //      https://code.google.com/p/android/issues/detail?id=58373
            // 2) Test if the installed package is not declared 'debuggable'.
            // 

            AndroidDevice debuggingDevice = Program.DebugProcess.NativeProcess.HostDevice;

            string runasPackageFileList = debuggingDevice.Shell (string.Format ("run-as {0}", Program.DebugProcess.NativeProcess.Name), "ls -l");

            if (runasPackageFileList.Contains (string.Format ("run-as: Package '{0}' is unknown", Program.DebugProcess.NativeProcess.Name)))
            {
              throw new InvalidOperationException ("Can not debug native code on this device/emulator.\nMore info: https://code.google.com/p/android/issues/detail?id=58373");
            }
            else if (runasPackageFileList.Contains (string.Format ("run-as: Package '{0}' is not debuggable", Program.DebugProcess.NativeProcess.Name)))
            {
              throw new InvalidOperationException (string.Format ("Package '{0}' is not debuggable.\nPlease ensure you're trying to connect to a 'Debug' application.\nAlternatively, completely uninstall the current app and try again.", Program.DebugProcess.NativeProcess.Name));
            }

            Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format ("Attaching to '{0}'...", Program.DebugProcess.NativeProcess.Name)), null, null);

            LoggingUtils.RequireOk (Program.Attach (m_sdmCallback), "Failed to attach to target application.");

            CLangDebuggeeThread currentThread = null;

            NativeDebugger.RunInterruptOperation (delegate (CLangDebugger debugger)
            {
              debugger.NativeProgram.RefreshAllThreads ();

              currentThread = debugger.NativeProgram.GetThread (debugger.NativeProgram.CurrentThreadId);

              if (currentThread == null)
              {
                // Lack of current thread is usually a good indication that connection/attaching failed.
                throw new InvalidOperationException (string.Format ("Failed to retrieve program's main thread (tid: {0}).", debugger.NativeProgram.CurrentThreadId));
              }
            });

            Broadcast (new DebugEngineEvent.ProgramCreate (), Program, null);

            Broadcast (new DebugEngineEvent.LoadComplete (), Program, currentThread);

            if (dwReason == enum_ATTACH_REASON.ATTACH_REASON_LAUNCH)
            {
              Broadcast (new DebugEngineEvent.EntryPoint (), Program, currentThread);
            }

            Broadcast (new DebugEngineEvent.AttachComplete (), Program, null);

            Broadcast (new DebugEngineEvent.DebuggerLogcatEvent (debuggingDevice), Program, null);

            Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.LogStatus, string.Format ("Attached successfully to '{0}'.", Program.DebugProcess.NativeProcess.Name)), null, null);

            Broadcast (new DebugEngineEvent.DebuggerConnectionEvent (DebugEngineEvent.DebuggerConnectionEvent.EventType.CloseDialog, string.Empty), null, null);
          }
          catch (Exception e)
          {
            LoggingUtils.HandleException (e);

            Broadcast (ad7Callback, new DebugEngineEvent.Error (e.Message, true), Program, null);

            Detach (Program);
          }
        });

        return Constants.S_OK;
      }
      catch (Exception e)
      {
        LoggingUtils.HandleException (e);

        Broadcast (ad7Callback, new DebugEngineEvent.Error (e.Message, true), Program, null);

        Detach (Program);

        return Constants.E_FAIL;
      }
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    public int Detach (DebuggeeProgram program)
    {
      LoggingUtils.PrintFunction ();

      try
      {
        if ((program.AttachedEngine != null) && (program.AttachedEngine.NativeDebugger != null))
        {
          program.AttachedEngine.NativeDebugger.Kill ();

          program.AttachedEngine.NativeDebugger.Dispose ();

          program.AttachedEngine.NativeDebugger = null;
        }

        if ((program.AttachedEngine != null) && (program.AttachedEngine.JavaDebugger != null))
        {
          program.AttachedEngine.JavaDebugger.Kill ();

          program.AttachedEngine.JavaDebugger.Dispose ();

          program.AttachedEngine.JavaDebugger = null;
        }

        return Constants.S_OK;
      }
      catch (Exception e)
      {
        LoggingUtils.HandleException (e);

        return Constants.E_FAIL;
      }
      finally
      {
        if ((program != null) && (program.AttachedEngine != null))
        {
          Broadcast (new DebugEngineEvent.ProgramDestroy (0), program, null);

          program.AttachedEngine = null;
        }

        m_cLangCallback = null;

        m_javaLangCallback = 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);
    }