<div dir="ltr">One of the new tests failed on at least one of the builders (I think Android).  I'm going to XFAIL that test and check that in momentarily.<div><br></div><div>-Todd</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Sep 3, 2016 at 5:18 PM, Todd Fiala via lldb-commits <span dir="ltr"><<a href="mailto:lldb-commits@lists.llvm.org" target="_blank">lldb-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: tfiala<br>
Date: Sat Sep  3 19:18:56 2016<br>
New Revision: 280604<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=280604&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=280604&view=rev</a><br>
Log:<br>
[NFC] Darwin llgs support from Week of Code<br>
<br>
This code represents the Week of Code work I did on bringing up<br>
lldb-server LLGS support for Darwin.  It does not include the<br>
Xcode project changes needed, as we don't want to throw that switch<br>
until more support is implemented (i.e. this change is inert, no<br>
build systems use it yet.  I've verified on Ubuntu 16.04, macOS<br>
Xcode and macOS cmake builds).<br>
<br>
This change does some minimal refactoring of code that is shared<br>
with the Linux LLGS portion, moving it from NativeProcessLinux into<br>
NativeProcessProtocol.  That code is also used by NativeProcessDarwin.<br>
<br>
Current state on Darwin:<br>
* Process launching is implemented.  (Attach is not).<br>
  Launching on devices has not yet been tested (FBS/BKS might<br>
  need a bit of work).<br>
* Inferior waitpid monitoring and communication of exit status<br>
  via MainLoop callback is implemented.<br>
* Memory read/write, breakpoints, thread register context, etc.<br>
  are not yet implemented.  This impacts process stop/resume, as<br>
  the initial launch suspended immediately starts the process<br>
  up and running because it doesn't know it is supposed to remain<br>
  stopped.<br>
* I implemented the equivalent of MachThreadList as<br>
  NativeThreadListDarwin, in anticipation that we might want to<br>
  factor out common parts into NativeThreadList{Protocol} and share<br>
  some code here.  After writing it, though, the fallout from merging<br>
  Mach Task/Process into a single concept plus some other minor<br>
  changes makes the whole NativeThreadListDarwin concept nothing more<br>
  than dead weight.  I am likely going to get rid of this class and<br>
  just manage it directly in NativeProcessDarwin, much like I did<br>
  for NativeProcessLinux.<br>
* There is a stub-out call for starting a STDIO thread.  That will<br>
  go away and adopt the MainLoop pselect-based IOObject reading.<br>
<br>
I am developing the fully-integrated changes in the following repo,<br>
which contains the necessary Xcode bits and the glue that enables<br>
lldb-debugserver on a macOS system:<br>
<br>
  <a href="https://github.com/tfiala/lldb/tree/llgs-darwin" rel="noreferrer" target="_blank">https://github.com/tfiala/<wbr>lldb/tree/llgs-darwin</a><br>
<br>
This change also breaks out a few of the lldb-server tests into<br>
their own directory, and adds some $qHostInfo tests (not sure why<br>
I didn't write those tests back when I initially implemented that<br>
on the Linux side).<br>
<br>
Added:<br>
    lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/exit-code/<br>
    lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/exit-code/Makefile<br>
    lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/exit-code/<wbr>TestGdbRemoteExitCode.py<br>
    lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/host-info/<br>
    lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/host-info/Makefile<br>
    lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/host-info/<wbr>TestGdbRemoteHostInfo.py<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFBundle.cpp<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFBundle.h<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFString.cpp<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFString.h<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFUtils.h<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>DarwinProcessLauncher.cpp<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>DarwinProcessLauncher.h<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/LaunchFlavor.h<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/MachException.<wbr>cpp<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/MachException.h<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeProcessDarwin.cpp<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeProcessDarwin.h<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadDarwin.cpp<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadDarwin.h<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadListDarwin.cpp<br>
    lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadListDarwin.h<br>
    lldb/trunk/tools/lldb-server/<wbr>Darwin/<br>
    lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/<br>
    lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>Info.plist<br>
    lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>entitlements.plist<br>
    lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>macos-entitlements.plist<br>
    lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>mig.defs<br>
Modified:<br>
    lldb/trunk/include/lldb/Host/<wbr>Debug.h<br>
    lldb/trunk/include/lldb/Host/<wbr>common/NativeProcessProtocol.h<br>
    lldb/trunk/include/lldb/lldb-<wbr>private-forward.h<br>
    lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/<wbr>TestGdbRemoteProcessInfo.py<br>
    lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/TestLldbGdbServer.py<br>
    lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/gdbremote_testcase.py<br>
    lldb/trunk/source/Host/common/<wbr>NativeProcessProtocol.cpp<br>
    lldb/trunk/source/Plugins/<wbr>Process/Linux/<wbr>NativeProcessLinux.cpp<br>
    lldb/trunk/source/Plugins/<wbr>Process/gdb-remote/<wbr>GDBRemoteCommunicationServerCo<wbr>mmon.cpp<br>
    lldb/trunk/source/Plugins/<wbr>Process/gdb-remote/<wbr>GDBRemoteCommunicationServerLL<wbr>GS.cpp<br>
    lldb/trunk/source/Target/<wbr>UnixSignals.cpp<br>
<br>
Modified: lldb/trunk/include/lldb/Host/<wbr>Debug.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/Debug.h?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/include/<wbr>lldb/Host/Debug.h?rev=280604&<wbr>r1=280603&r2=280604&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/include/lldb/Host/<wbr>Debug.h (original)<br>
+++ lldb/trunk/include/lldb/Host/<wbr>Debug.h Sat Sep  3 19:18:56 2016<br>
@@ -201,7 +201,7 @@ namespace lldb_private {<br>
             {<br>
                 uint64_t type;<br>
                 uint32_t data_count;<br>
-                lldb::addr_t data[2];<br>
+                lldb::addr_t data[8];<br>
             } exception;<br>
         } details;<br>
     };<br>
<br>
Modified: lldb/trunk/include/lldb/Host/<wbr>common/NativeProcessProtocol.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/include/<wbr>lldb/Host/common/<wbr>NativeProcessProtocol.h?rev=<wbr>280604&r1=280603&r2=280604&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/include/lldb/Host/<wbr>common/NativeProcessProtocol.h (original)<br>
+++ lldb/trunk/include/lldb/Host/<wbr>common/NativeProcessProtocol.h Sat Sep  3 19:18:56 2016<br>
@@ -37,12 +37,6 @@ namespace lldb_private<br>
<br>
     public:<br>
<br>
-        // lldb_private::Host calls should be used to launch a process for debugging, and<br>
-        // then the process should be attached to. When attaching to a process<br>
-        // lldb_private::Host calls should be used to locate the process to attach to,<br>
-        // and then this function should be called.<br>
-        NativeProcessProtocol (lldb::pid_t pid);<br>
-<br>
         virtual ~NativeProcessProtocol ()<br>
         {<br>
         }<br>
@@ -379,6 +373,12 @@ namespace lldb_private<br>
         int m_terminal_fd;<br>
         uint32_t m_stop_id;<br>
<br>
+        // lldb_private::Host calls should be used to launch a process for debugging, and<br>
+        // then the process should be attached to. When attaching to a process<br>
+        // lldb_private::Host calls should be used to locate the process to attach to,<br>
+        // and then this function should be called.<br>
+        NativeProcessProtocol (lldb::pid_t pid);<br>
+<br>
         // ------------------------------<wbr>-----------------------------<br>
         // Internal interface for state handling<br>
         // ------------------------------<wbr>-----------------------------<br>
@@ -415,6 +415,12 @@ namespace lldb_private<br>
         NativeThreadProtocolSP<br>
         GetThreadByIDUnlocked (lldb::tid_t tid);<br>
<br>
+        // ------------------------------<wbr>-----------------------------<br>
+        // Static helper methods for derived classes.<br>
+        // ------------------------------<wbr>-----------------------------<br>
+        static Error<br>
+        ResolveProcessArchitecture(<wbr>lldb::pid_t pid, ArchSpec &arch);<br>
+<br>
     private:<br>
<br>
         void<br>
<br>
Modified: lldb/trunk/include/lldb/lldb-<wbr>private-forward.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-private-forward.h?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/include/<wbr>lldb/lldb-private-forward.h?<wbr>rev=280604&r1=280603&r2=<wbr>280604&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/include/lldb/lldb-<wbr>private-forward.h (original)<br>
+++ lldb/trunk/include/lldb/lldb-<wbr>private-forward.h Sat Sep  3 19:18:56 2016<br>
@@ -24,6 +24,7 @@ namespace lldb_private<br>
     class NativeProcessProtocol;<br>
     class NativeRegisterContext;<br>
     class NativeThreadProtocol;<br>
+    class ResumeActionList;<br>
     class UnixSignals;<br>
<br>
     // ------------------------------<wbr>------------------------------<wbr>---<br>
<br>
Modified: lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/<wbr>TestGdbRemoteProcessInfo.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteProcessInfo.py?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/packages/<wbr>Python/lldbsuite/test/tools/<wbr>lldb-server/<wbr>TestGdbRemoteProcessInfo.py?<wbr>rev=280604&r1=280603&r2=<wbr>280604&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/<wbr>TestGdbRemoteProcessInfo.py (original)<br>
+++ lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/<wbr>TestGdbRemoteProcessInfo.py Sat Sep  3 19:18:56 2016<br>
@@ -155,6 +155,13 @@ class TestGdbRemoteProcessInfo(<wbr>gdbremote<br>
         self.build()<br>
         self.qProcessInfo_contains_<wbr>keys(set(['cputype', 'cpusubtype']))<br>
<br>
+    @skipUnlessDarwin<br>
+    @llgs_test<br>
+    def test_qProcessInfo_contains_<wbr>cputype_cpusubtype_llgs_<wbr>darwin(self):<br>
+        self.init_llgs_test()<br>
+        self.build()<br>
+        self.qProcessInfo_contains_<wbr>keys(set(['cputype', 'cpusubtype']))<br>
+<br>
     @skipUnlessPlatform(["linux"])<br>
     @llgs_test<br>
     def test_qProcessInfo_contains_<wbr>triple_llgs_linux(self):<br>
@@ -169,6 +176,16 @@ class TestGdbRemoteProcessInfo(<wbr>gdbremote<br>
         self.build()<br>
         # We don't expect to see triple on darwin.  If we do, we'll prefer triple<br>
         # to cputype/cpusubtype and skip some darwin-based ProcessGDBRemote ArchSpec setup<br>
+        # for the remote Host and Process.<br>
+        self.qProcessInfo_does_not_<wbr>contain_keys(set(['triple']))<br>
+<br>
+    @skipUnlessDarwin<br>
+    @llgs_test<br>
+    def test_qProcessInfo_does_not_<wbr>contain_triple_llgs_darwin(<wbr>self):<br>
+        self.init_llgs_test()<br>
+        self.build()<br>
+        # We don't expect to see triple on darwin.  If we do, we'll prefer triple<br>
+        # to cputype/cpusubtype and skip some darwin-based ProcessGDBRemote ArchSpec setup<br>
         # for the remote Host and Process.<br>
         self.qProcessInfo_does_not_<wbr>contain_keys(set(['triple']))<br>
<br>
<br>
Modified: lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/TestLldbGdbServer.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/packages/<wbr>Python/lldbsuite/test/tools/<wbr>lldb-server/TestLldbGdbServer.<wbr>py?rev=280604&r1=280603&r2=<wbr>280604&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/TestLldbGdbServer.py (original)<br>
+++ lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/TestLldbGdbServer.py Sat Sep  3 19:18:56 2016<br>
@@ -97,101 +97,6 @@ class LldbGdbServerTestCase(<wbr>gdbremote_te<br>
         self.init_llgs_test()<br>
         self.list_threads_in_stop_<wbr>reply_supported()<br>
<br>
-    def install_and_create_launch_<wbr>args(self):<br>
-        exe_path = os.path.abspath('a.out')<br>
-        if not lldb.remote_platform:<br>
-            return [exe_path]<br>
-        remote_path = lldbutil.append_to_process_<wbr>working_directory(os.path.<wbr>basename(exe_path))<br>
-        remote_file_spec = lldb.SBFileSpec(remote_path, False)<br>
-        err = lldb.remote_platform.Install(<wbr>lldb.SBFileSpec(exe_path, True), remote_file_spec)<br>
-        if err.Fail():<br>
-            raise Exception("remote_platform.<wbr>Install('%s', '%s') failed: %s" % (exe_path, remote_path, err))<br>
-        return [remote_path]<br>
-<br>
-    def start_inferior(self):<br>
-        launch_args = self.install_and_create_<wbr>launch_args()<br>
-<br>
-        server = self.connect_to_debug_monitor(<wbr>)<br>
-        self.assertIsNotNone(server)<br>
-<br>
-        self.add_no_ack_remote_stream(<wbr>)<br>
-        self.test_sequence.add_log_<wbr>lines(<br>
-            ["read packet: %s" % lldbgdbserverutils.build_<wbr>gdbremote_A_packet(launch_<wbr>args),<br>
-             "send packet: $OK#9a"],<br>
-            True)<br>
-        self.expect_gdbremote_<wbr>sequence()<br>
-<br>
-    @debugserver_test<br>
-    def test_start_inferior_<wbr>debugserver(self):<br>
-        self.init_debugserver_test()<br>
-        self.build()<br>
-        self.start_inferior()<br>
-<br>
-    @llgs_test<br>
-    def test_start_inferior_llgs(self)<wbr>:<br>
-        self.init_llgs_test()<br>
-        self.build()<br>
-        self.start_inferior()<br>
-<br>
-    def inferior_exit_0(self):<br>
-        launch_args = self.install_and_create_<wbr>launch_args()<br>
-<br>
-        server = self.connect_to_debug_monitor(<wbr>)<br>
-        self.assertIsNotNone(server)<br>
-<br>
-        self.add_no_ack_remote_stream(<wbr>)<br>
-        self.add_verified_launch_<wbr>packets(launch_args)<br>
-        self.test_sequence.add_log_<wbr>lines(<br>
-            ["read packet: $vCont;c#a8",<br>
-             "send packet: $W00#00"],<br>
-            True)<br>
-<br>
-        self.expect_gdbremote_<wbr>sequence()<br>
-<br>
-    @debugserver_test<br>
-    def test_inferior_exit_0_<wbr>debugserver(self):<br>
-        self.init_debugserver_test()<br>
-        self.build()<br>
-        self.inferior_exit_0()<br>
-<br>
-    @llgs_test<br>
-    def test_inferior_exit_0_llgs(<wbr>self):<br>
-        self.init_llgs_test()<br>
-        self.build()<br>
-        self.inferior_exit_0()<br>
-<br>
-    def inferior_exit_42(self):<br>
-        launch_args = self.install_and_create_<wbr>launch_args()<br>
-<br>
-        server = self.connect_to_debug_monitor(<wbr>)<br>
-        self.assertIsNotNone(server)<br>
-<br>
-        RETVAL = 42<br>
-<br>
-        # build launch args<br>
-        launch_args += ["retval:%d" % RETVAL]<br>
-<br>
-        self.add_no_ack_remote_stream(<wbr>)<br>
-        self.add_verified_launch_<wbr>packets(launch_args)<br>
-        self.test_sequence.add_log_<wbr>lines(<br>
-            ["read packet: $vCont;c#a8",<br>
-             "send packet: $W{0:02x}#00".format(RETVAL)],<br>
-            True)<br>
-<br>
-        self.expect_gdbremote_<wbr>sequence()<br>
-<br>
-    @debugserver_test<br>
-    def test_inferior_exit_42_<wbr>debugserver(self):<br>
-        self.init_debugserver_test()<br>
-        self.build()<br>
-        self.inferior_exit_42()<br>
-<br>
-    @llgs_test<br>
-    def test_inferior_exit_42_llgs(<wbr>self):<br>
-        self.init_llgs_test()<br>
-        self.build()<br>
-        self.inferior_exit_42()<br>
-<br>
     def c_packet_works(self):<br>
         launch_args = self.install_and_create_<wbr>launch_args()<br>
<br>
<br>
Added: lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/exit-code/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/exit-code/Makefile?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/packages/<wbr>Python/lldbsuite/test/tools/<wbr>lldb-server/exit-code/<wbr>Makefile?rev=280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/exit-code/Makefile (added)<br>
+++ lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/exit-code/Makefile Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,10 @@<br>
+LEVEL = ../../../make<br>
+<br>
+VPATH = ..<br>
+<br>
+override CFLAGS_EXTRAS += -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS<br>
+ENABLE_THREADS := YES<br>
+CXX_SOURCES := main.cpp<br>
+MAKE_DSYM :=NO<br>
+<br>
+include $(LEVEL)/Makefile.rules<br>
<br>
Added: lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/exit-code/<wbr>TestGdbRemoteExitCode.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/exit-code/TestGdbRemoteExitCode.py?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/packages/<wbr>Python/lldbsuite/test/tools/<wbr>lldb-server/exit-code/<wbr>TestGdbRemoteExitCode.py?rev=<wbr>280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/exit-code/<wbr>TestGdbRemoteExitCode.py (added)<br>
+++ lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/exit-code/<wbr>TestGdbRemoteExitCode.py Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,124 @@<br>
+from __future__ import print_function<br>
+<br>
+# lldb test suite imports<br>
+from lldbsuite.test.decorators import *<br>
+from lldbsuite.test.lldbtest import TestBase<br>
+<br>
+# gdb-remote-specific imports<br>
+import lldbgdbserverutils<br>
+from gdbremote_testcase import GdbRemoteTestCaseBase<br>
+<br>
+<br>
+class TestGdbRemoteExitCode(<wbr>GdbRemoteTestCaseBase):<br>
+<br>
+    mydir = TestBase.compute_mydir(__file_<wbr>_)<br>
+<br>
+    FAILED_LAUNCH_CODE = "E08"<br>
+<br>
+    def get_launch_fail_reason(self):<br>
+        self.reset_test_sequence()<br>
+        self.test_sequence.add_log_<wbr>lines(<br>
+            ["read packet: $qLaunchSuccess#00"],<br>
+            True)<br>
+        self.test_sequence.add_log_<wbr>lines(<br>
+            [{"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",<br>
+              "capture": {1: "launch_result"}}],<br>
+            True)<br>
+        context = self.expect_gdbremote_<wbr>sequence()<br>
+        self.assertIsNotNone(context)<br>
+        return context.get("launch_result")[<wbr>1:]<br>
+<br>
+    def start_inferior(self):<br>
+        launch_args = self.install_and_create_<wbr>launch_args()<br>
+<br>
+        server = self.connect_to_debug_monitor(<wbr>)<br>
+        self.assertIsNotNone(server)<br>
+<br>
+        self.add_no_ack_remote_stream(<wbr>)<br>
+        self.test_sequence.add_log_<wbr>lines(<br>
+            ["read packet: %s" % lldbgdbserverutils.build_<wbr>gdbremote_A_packet(<br>
+                launch_args)],<br>
+            True)<br>
+        self.test_sequence.add_log_<wbr>lines(<br>
+            [{"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",<br>
+              "capture": {1: "A_result"}}],<br>
+            True)<br>
+        context = self.expect_gdbremote_<wbr>sequence()<br>
+        self.assertIsNotNone(context)<br>
+<br>
+        launch_result = context.get("A_result")<br>
+        self.assertIsNotNone(launch_<wbr>result)<br>
+        if launch_result == self.FAILED_LAUNCH_CODE:<br>
+            fail_reason = self.get_launch_fail_reason()<br>
+            self.fail("failed to launch inferior: " + fail_reason)<br>
+<br>
+    @debugserver_test<br>
+    def test_start_inferior_<wbr>debugserver(self):<br>
+        self.init_debugserver_test()<br>
+        self.build()<br>
+        self.start_inferior()<br>
+<br>
+    @llgs_test<br>
+    def test_start_inferior_llgs(self)<wbr>:<br>
+        self.init_llgs_test()<br>
+        self.build()<br>
+        self.start_inferior()<br>
+<br>
+    def inferior_exit_0(self):<br>
+        launch_args = self.install_and_create_<wbr>launch_args()<br>
+<br>
+        server = self.connect_to_debug_monitor(<wbr>)<br>
+        self.assertIsNotNone(server)<br>
+<br>
+        self.add_no_ack_remote_stream(<wbr>)<br>
+        self.add_verified_launch_<wbr>packets(launch_args)<br>
+        self.test_sequence.add_log_<wbr>lines(<br>
+            ["read packet: $vCont;c#a8",<br>
+             "send packet: $W00#00"],<br>
+            True)<br>
+<br>
+        self.expect_gdbremote_<wbr>sequence()<br>
+<br>
+    @debugserver_test<br>
+    def test_inferior_exit_0_<wbr>debugserver(self):<br>
+        self.init_debugserver_test()<br>
+        self.build()<br>
+        self.inferior_exit_0()<br>
+<br>
+    @llgs_test<br>
+    def test_inferior_exit_0_llgs(<wbr>self):<br>
+        self.init_llgs_test()<br>
+        self.build()<br>
+        self.inferior_exit_0()<br>
+<br>
+    def inferior_exit_42(self):<br>
+        launch_args = self.install_and_create_<wbr>launch_args()<br>
+<br>
+        server = self.connect_to_debug_monitor(<wbr>)<br>
+        self.assertIsNotNone(server)<br>
+<br>
+        RETVAL = 42<br>
+<br>
+        # build launch args<br>
+        launch_args += ["retval:%d" % RETVAL]<br>
+<br>
+        self.add_no_ack_remote_stream(<wbr>)<br>
+        self.add_verified_launch_<wbr>packets(launch_args)<br>
+        self.test_sequence.add_log_<wbr>lines(<br>
+            ["read packet: $vCont;c#a8",<br>
+             "send packet: $W{0:02x}#00".format(RETVAL)],<br>
+            True)<br>
+<br>
+        self.expect_gdbremote_<wbr>sequence()<br>
+<br>
+    @debugserver_test<br>
+    def test_inferior_exit_42_<wbr>debugserver(self):<br>
+        self.init_debugserver_test()<br>
+        self.build()<br>
+        self.inferior_exit_42()<br>
+<br>
+    @llgs_test<br>
+    def test_inferior_exit_42_llgs(<wbr>self):<br>
+        self.init_llgs_test()<br>
+        self.build()<br>
+        self.inferior_exit_42()<br>
<br>
Modified: lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/gdbremote_testcase.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/packages/<wbr>Python/lldbsuite/test/tools/<wbr>lldb-server/gdbremote_<wbr>testcase.py?rev=280604&r1=<wbr>280603&r2=280604&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/gdbremote_testcase.py (original)<br>
+++ lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/gdbremote_testcase.py Sat Sep  3 19:18:56 2016<br>
@@ -133,7 +133,7 @@ class GdbRemoteTestCaseBase(<wbr>TestBase):<br>
             self.debug_monitor_extra_args.<wbr>append("--log-file=" + log_file)<br>
             self.debug_monitor_extra_args.<wbr>append("--log-channels={}".<wbr>format(":".join(lldbtest_<wbr>config.channels)))<br>
         else:<br>
-            self.debug_monitor_extra_args = ["--log-file=" + self.log_file, "--log-flags=0x800000"]<br>
+            self.debug_monitor_extra_args = ["--log-file=" + log_file, "--log-flags=0x800000"]<br>
<br>
     def get_next_port(self):<br>
         return 12000 + random.randint(0,3999)<br>
@@ -1370,3 +1370,16 @@ class GdbRemoteTestCaseBase(<wbr>TestBase):<br>
     def maybe_strict_output_regex(<wbr>self, regex):<br>
         return '.*'+regex+'.*' if lldbplatformutil.<wbr>hasChattyStderr(self) else '^'+regex+'$'<br>
<br>
+    def install_and_create_launch_<wbr>args(self):<br>
+        exe_path = os.path.abspath('a.out')<br>
+        if not lldb.remote_platform:<br>
+            return [exe_path]<br>
+        remote_path = lldbutil.append_to_process_<wbr>working_directory(<br>
+            os.path.basename(exe_path))<br>
+        remote_file_spec = lldb.SBFileSpec(remote_path, False)<br>
+        err = lldb.remote_platform.Install(<wbr>lldb.SBFileSpec(exe_path, True),<br>
+                                           remote_file_spec)<br>
+        if err.Fail():<br>
+            raise Exception("remote_platform.<wbr>Install('%s', '%s') failed: %s" %<br>
+                            (exe_path, remote_path, err))<br>
+        return [remote_path]<br>
<br>
Added: lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/host-info/Makefile<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/host-info/Makefile?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/packages/<wbr>Python/lldbsuite/test/tools/<wbr>lldb-server/host-info/<wbr>Makefile?rev=280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/host-info/Makefile (added)<br>
+++ lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/host-info/Makefile Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,10 @@<br>
+LEVEL = ../../../make<br>
+<br>
+VPATH = ..<br>
+<br>
+override CFLAGS_EXTRAS += -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS<br>
+ENABLE_THREADS := YES<br>
+CXX_SOURCES := main.cpp<br>
+MAKE_DSYM :=NO<br>
+<br>
+include $(LEVEL)/Makefile.rules<br>
<br>
Added: lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/host-info/<wbr>TestGdbRemoteHostInfo.py<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/host-info/TestGdbRemoteHostInfo.py?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/packages/<wbr>Python/lldbsuite/test/tools/<wbr>lldb-server/host-info/<wbr>TestGdbRemoteHostInfo.py?rev=<wbr>280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/host-info/<wbr>TestGdbRemoteHostInfo.py (added)<br>
+++ lldb/trunk/packages/Python/<wbr>lldbsuite/test/tools/lldb-<wbr>server/host-info/<wbr>TestGdbRemoteHostInfo.py Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,125 @@<br>
+from __future__ import print_function<br>
+<br>
+# lldb test suite imports<br>
+from lldbsuite.test.decorators import *<br>
+from lldbsuite.test.lldbtest import TestBase<br>
+<br>
+# gdb-remote-specific imports<br>
+import lldbgdbserverutils<br>
+from gdbremote_testcase import GdbRemoteTestCaseBase<br>
+<br>
+<br>
+class TestGdbRemoteHostInfo(<wbr>GdbRemoteTestCaseBase):<br>
+<br>
+    mydir = TestBase.compute_mydir(__file_<wbr>_)<br>
+<br>
+    KNOWN_HOST_INFO_KEYS = set([<br>
+        "cputype",<br>
+        "cpusubtype",<br>
+        "distribution_id",<br>
+        "endian",<br>
+        "hostname",<br>
+        "ostype",<br>
+        "os_build",<br>
+        "os_kernel",<br>
+        "os_version",<br>
+        "ptrsize",<br>
+        "triple",<br>
+        "vendor",<br>
+        "watchpoint_exceptions_<wbr>received"<br>
+    ])<br>
+<br>
+    DARWIN_REQUIRED_HOST_INFO_KEYS = set([<br>
+        "cputype",<br>
+        "cpusubtype",<br>
+        "endian",<br>
+        "ostype",<br>
+        "ptrsize",<br>
+        "vendor",<br>
+        "watchpoint_exceptions_<wbr>received"<br>
+    ])<br>
+<br>
+    def add_host_info_collection_<wbr>packets(self):<br>
+        self.test_sequence.add_log_<wbr>lines(<br>
+            ["read packet: $qHostInfo#9b",<br>
+             {"direction": "send", "regex": r"^\$(.+)#[0-9a-fA-F]{2}$",<br>
+              "capture": {1: "host_info_raw"}}],<br>
+            True)<br>
+<br>
+    def parse_host_info_response(self, context):<br>
+        # Ensure we have a host info response.<br>
+        self.assertIsNotNone(context)<br>
+        host_info_raw = context.get("host_info_raw")<br>
+        self.assertIsNotNone(host_<wbr>info_raw)<br>
+<br>
+        # Pull out key:value; pairs.<br>
+        host_info_dict = {match.group(1): match.group(2)<br>
+                          for match in re.finditer(r"([^:]+):([^;]+);<wbr>",<br>
+                                                   host_info_raw)}<br>
+<br>
+        import pprint<br>
+        print("\nqHostInfo response:")<br>
+        pprint.pprint(host_info_dict)<br>
+<br>
+        # Validate keys are known.<br>
+        for (key, val) in list(host_info_dict.items()):<br>
+            self.assertTrue(key in self.KNOWN_HOST_INFO_KEYS,<br>
+                            "unknown qHostInfo key: " + key)<br>
+            self.assertIsNotNone(val)<br>
+<br>
+        # Return the key:val pairs.<br>
+        return host_info_dict<br>
+<br>
+    def get_qHostInfo_response(self):<br>
+        # Launch the debug monitor stub, attaching to the inferior.<br>
+        server = self.connect_to_debug_monitor(<wbr>)<br>
+        self.assertIsNotNone(server)<br>
+        self.add_no_ack_remote_stream(<wbr>)<br>
+<br>
+        # Request qHostInfo and get response<br>
+        self.add_host_info_collection_<wbr>packets()<br>
+        context = self.expect_gdbremote_<wbr>sequence()<br>
+        self.assertIsNotNone(context)<br>
+<br>
+        # Parse qHostInfo response.<br>
+        host_info = self.parse_host_info_response(<wbr>context)<br>
+        self.assertIsNotNone(host_<wbr>info)<br>
+        self.assertGreater(len(host_<wbr>info), 0, "qHostInfo should have returned "<br>
+                           "at least one key:val pair.")<br>
+        return host_info<br>
+<br>
+    def validate_darwin_minimum_host_<wbr>info_keys(self, host_info_dict):<br>
+        self.assertIsNotNone(host_<wbr>info_dict)<br>
+        missing_keys = [key for key in self.DARWIN_REQUIRED_HOST_<wbr>INFO_KEYS<br>
+                        if key not in host_info_dict]<br>
+        self.assertEquals(0, len(missing_keys),<br>
+                          "qHostInfo is missing the following required "<br>
+                          "keys: " + str(missing_keys))<br>
+<br>
+    @debugserver_test<br>
+    def test_qHostInfo_returns_at_<wbr>least_one_key_val_pair_<wbr>debugserver(self):<br>
+        self.init_debugserver_test()<br>
+        self.build()<br>
+        self.get_qHostInfo_response()<br>
+<br>
+    @llgs_test<br>
+    def test_qHostInfo_returns_at_<wbr>least_one_key_val_pair_llgs(<wbr>self):<br>
+        self.init_llgs_test()<br>
+        self.build()<br>
+        self.get_qHostInfo_response()<br>
+<br>
+    @skipUnlessDarwin<br>
+    @debugserver_test<br>
+    def test_qHostInfo_contains_<wbr>darwin_required_keys_<wbr>debugserver(self):<br>
+        self.init_debugserver_test()<br>
+        self.build()<br>
+        host_info_dict = self.get_qHostInfo_response()<br>
+        self.validate_darwin_minimum_<wbr>host_info_keys(host_info_dict)<br>
+<br>
+    @skipUnlessDarwin<br>
+    @llgs_test<br>
+    def test_qHostInfo_contains_<wbr>darwin_required_keys_llgs(<wbr>self):<br>
+        self.init_llgs_test()<br>
+        self.build()<br>
+        host_info_dict = self.get_qHostInfo_response()<br>
+        self.validate_darwin_minimum_<wbr>host_info_keys(host_info_dict)<br>
<br>
Modified: lldb/trunk/source/Host/common/<wbr>NativeProcessProtocol.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/NativeProcessProtocol.cpp?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Host/common/<wbr>NativeProcessProtocol.cpp?rev=<wbr>280604&r1=280603&r2=280604&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Host/common/<wbr>NativeProcessProtocol.cpp (original)<br>
+++ lldb/trunk/source/Host/common/<wbr>NativeProcessProtocol.cpp Sat Sep  3 19:18:56 2016<br>
@@ -12,12 +12,15 @@<br>
 #include "lldb/lldb-enumerations.h"<br>
 #include "lldb/Core/ArchSpec.h"<br>
 #include "lldb/Core/Log.h"<br>
+#include "lldb/Core/ModuleSpec.h"<br>
 #include "lldb/Core/State.h"<br>
 #include "lldb/Host/Host.h"<br>
 #include "lldb/Host/common/<wbr>NativeRegisterContext.h"<br>
-<br>
 #include "lldb/Host/common/<wbr>NativeThreadProtocol.h"<br>
 #include "lldb/Host/common/<wbr>SoftwareBreakpoint.h"<br>
+#include "lldb/Symbol/ObjectFile.h"<br>
+#include "lldb/Target/Process.h"<br>
+#include "lldb/Utility/LLDBAssert.h"<br>
<br>
 using namespace lldb;<br>
 using namespace lldb_private;<br>
@@ -436,6 +439,29 @@ NativeProcessProtocol::<wbr>DoStopIDBumped (u<br>
     // Default implementation does nothing.<br>
 }<br>
<br>
+Error<br>
+NativeProcessProtocol::<wbr>ResolveProcessArchitecture(<wbr>lldb::pid_t pid,<br>
+                                                  ArchSpec &arch)<br>
+{<br>
+    // Grab process info for the running process.<br>
+    ProcessInstanceInfo process_info;<br>
+    if (!Host::GetProcessInfo(pid, process_info))<br>
+        return Error("failed to get process info");<br>
+<br>
+    // Resolve the executable module.<br>
+    ModuleSpecList module_specs;<br>
+    if (!ObjectFile::<wbr>GetModuleSpecifications(<wbr>process_info.<wbr>GetExecutableFile(),<br>
+                                             0, 0, module_specs))<br>
+        return Error("failed to get module specifications");<br>
+    lldbassert(module_specs.<wbr>GetSize() == 1);<br>
+<br>
+    arch = module_specs.<wbr>GetModuleSpecRefAtIndex(0).<wbr>GetArchitecture();<br>
+    if (arch.IsValid())<br>
+        return Error();<br>
+    else<br>
+        return Error("failed to retrieve a valid architecture from the exe module");<br>
+}<br>
+<br>
 #ifndef __linux__<br>
 // These need to be implemented to support lldb-gdb-server on a given platform. Stubs are<br>
 // provided to make the rest of the code link on non-supported platforms.<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFBundle.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/CFBundle.cpp?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>CFBundle.cpp?rev=280604&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFBundle.cpp (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFBundle.cpp Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,97 @@<br>
+//===-- CFBundle.cpp ------------------------------<wbr>--------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//  Created by Greg Clayton on 1/16/08.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "CFBundle.h"<br>
+#include "CFString.h"<br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// CFBundle constructor<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+CFBundle::CFBundle(const char *path) :<br>
+    CFReleaser<CFBundleRef>(),<br>
+    m_bundle_url()<br>
+{<br>
+    if (path && path[0])<br>
+        SetPath(path);<br>
+}<br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// CFBundle copy constructor<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+CFBundle::CFBundle(const CFBundle& rhs) :<br>
+    CFReleaser<CFBundleRef>(rhs),<br>
+    m_bundle_url(rhs.m_bundle_url)<br>
+{<br>
+<br>
+}<br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// CFBundle copy constructor<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+CFBundle&<br>
+CFBundle::operator=(const CFBundle& rhs)<br>
+{<br>
+    *this = rhs;<br>
+    return *this;<br>
+}<br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// Destructor<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+CFBundle::~CFBundle()<br>
+{<br>
+}<br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// Set the path for a bundle by supplying a<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+bool<br>
+CFBundle::SetPath (const char *path)<br>
+{<br>
+    CFAllocatorRef alloc = kCFAllocatorDefault;<br>
+    // Release our old bundle and ULR<br>
+    reset();    // This class is a CFReleaser<CFBundleRef><br>
+    m_bundle_url.reset();<br>
+    // Make a CFStringRef from the supplied path<br>
+    CFString cf_path;<br>
+    cf_path.<wbr>SetFileSystemRepresentation(<wbr>path);<br>
+    if (cf_path.get())<br>
+    {<br>
+        // Make our Bundle URL<br>
+        m_bundle_url.reset (::<wbr>CFURLCreateWithFileSystemPath (alloc, cf_path.get(), kCFURLPOSIXPathStyle, true));<br>
+        if (m_bundle_url.get())<br>
+        {<br>
+            reset (::CFBundleCreate (alloc, m_bundle_url.get()));<br>
+        }<br>
+    }<br>
+    return get() != NULL;<br>
+}<br>
+<br>
+CFStringRef<br>
+CFBundle::GetIdentifier () const<br>
+{<br>
+    CFBundleRef bundle = get();<br>
+    if (bundle != NULL)<br>
+        return ::CFBundleGetIdentifier (bundle);<br>
+    return NULL;<br>
+}<br>
+<br>
+<br>
+CFURLRef<br>
+CFBundle::CopyExecutableURL () const<br>
+{<br>
+    CFBundleRef bundle = get();<br>
+    if (bundle != NULL)<br>
+        return CFBundleCopyExecutableURL(<wbr>bundle);<br>
+    return NULL;<br>
+}<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFBundle.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/CFBundle.h?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>CFBundle.h?rev=280604&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFBundle.h (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFBundle.h Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,43 @@<br>
+//===-- CFBundle.h ------------------------------<wbr>----------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//  Created by Greg Clayton on 1/16/08.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef __CFBundle_h__<br>
+#define __CFBundle_h__<br>
+<br>
+#include "CFUtils.h"<br>
+<br>
+class CFBundle : public CFReleaser<CFBundleRef><br>
+{<br>
+public:<br>
+    //----------------------------<wbr>------------------------------<wbr>--------<br>
+    // Constructors and Destructors<br>
+    //----------------------------<wbr>------------------------------<wbr>--------<br>
+    CFBundle(const char *path = NULL);<br>
+    CFBundle(const CFBundle& rhs);<br>
+    CFBundle& operator=(const CFBundle& rhs);<br>
+    virtual<br>
+    ~CFBundle();<br>
+    bool<br>
+    SetPath (const char *path);<br>
+<br>
+    CFStringRef<br>
+    GetIdentifier () const;<br>
+<br>
+    CFURLRef<br>
+    CopyExecutableURL () const;<br>
+<br>
+protected:<br>
+        CFReleaser<CFURLRef> m_bundle_url;<br>
+};<br>
+<br>
+#endif // #ifndef __CFBundle_h__<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFString.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/CFString.cpp?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>CFString.cpp?rev=280604&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFString.cpp (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFString.cpp Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,201 @@<br>
+//===-- CFString.cpp ------------------------------<wbr>--------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//  Created by Greg Clayton on 1/16/08.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "CFString.h"<br>
+#include <string><br>
+#include <glob.h><br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// CFString constructor<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+CFString::CFString(<wbr>CFStringRef s) :<br>
+    CFReleaser<CFStringRef> (s)<br>
+{<br>
+}<br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// CFString copy constructor<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+CFString::CFString(const CFString& rhs) :<br>
+    CFReleaser<CFStringRef> (rhs)<br>
+{<br>
+<br>
+}<br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// CFString copy constructor<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+CFString&<br>
+CFString::operator=(const CFString& rhs)<br>
+{<br>
+    if (this != &rhs)<br>
+        *this = rhs;<br>
+    return *this;<br>
+}<br>
+<br>
+CFString::CFString (const char *cstr, CFStringEncoding cstr_encoding) :<br>
+    CFReleaser<CFStringRef> ()<br>
+{<br>
+    if (cstr && cstr[0])<br>
+    {<br>
+        reset(::<wbr>CFStringCreateWithCString(<wbr>kCFAllocatorDefault, cstr, cstr_encoding));<br>
+    }<br>
+}<br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// Destructor<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+CFString::~CFString()<br>
+{<br>
+}<br>
+<br>
+const char *<br>
+CFString::<wbr>GetFileSystemRepresentation(<wbr>std::string& s)<br>
+{<br>
+    return CFString::<wbr>FileSystemRepresentation(get()<wbr>, s);<br>
+}<br>
+<br>
+CFStringRef<br>
+CFString::<wbr>SetFileSystemRepresentation (const char *path)<br>
+{<br>
+    CFStringRef new_value = NULL;<br>
+    if (path && path[0])<br>
+        new_value = ::<wbr>CFStringCreateWithFileSystemRe<wbr>presentation (kCFAllocatorDefault, path);<br>
+    reset(new_value);<br>
+    return get();<br>
+}<br>
+<br>
+<br>
+CFStringRef<br>
+CFString::<wbr>SetFileSystemRepresentationFro<wbr>mCFType (CFTypeRef cf_type)<br>
+{<br>
+    CFStringRef new_value = NULL;<br>
+    if (cf_type != NULL)<br>
+    {<br>
+        CFTypeID cf_type_id = ::CFGetTypeID(cf_type);<br>
+<br>
+        if (cf_type_id == ::CFStringGetTypeID())<br>
+        {<br>
+            // Retain since we are using the existing object<br>
+            new_value = (CFStringRef)::CFRetain(cf_<wbr>type);<br>
+        }<br>
+        else if (cf_type_id == ::CFURLGetTypeID())<br>
+        {<br>
+            new_value = ::CFURLCopyFileSystemPath((<wbr>CFURLRef)cf_type, kCFURLPOSIXPathStyle);<br>
+        }<br>
+    }<br>
+    reset(new_value);<br>
+    return get();<br>
+}<br>
+<br>
+CFStringRef<br>
+CFString::<wbr>SetFileSystemRepresentationAnd<wbr>ExpandTilde (const char *path)<br>
+{<br>
+    std::string expanded_path;<br>
+    if (CFString::GlobPath(path, expanded_path))<br>
+        SetFileSystemRepresentation(<wbr>expanded_path.c_str());<br>
+    else<br>
+        reset();<br>
+    return get();<br>
+}<br>
+<br>
+const char *<br>
+CFString::UTF8(std::string& str)<br>
+{<br>
+    return CFString::UTF8(get(), str);<br>
+}<br>
+<br>
+// Static function that puts a copy of the UTF8 contents of CF_STR into STR<br>
+// and returns the C string pointer that is contained in STR when successful, else<br>
+// NULL is returned. This allows the std::string parameter to own the extracted string,<br>
+// and also allows that string to be returned as a C string pointer that can be used.<br>
+<br>
+const char *<br>
+CFString::UTF8 (CFStringRef cf_str, std::string& str)<br>
+{<br>
+    if (cf_str)<br>
+    {<br>
+        const CFStringEncoding encoding = kCFStringEncodingUTF8;<br>
+        CFIndex max_utf8_str_len = CFStringGetLength (cf_str);<br>
+        max_utf8_str_len = CFStringGetMaximumSizeForEncod<wbr>ing (max_utf8_str_len, encoding);<br>
+        if (max_utf8_str_len > 0)<br>
+        {<br>
+            str.resize(max_utf8_str_len);<br>
+            if (!str.empty())<br>
+            {<br>
+                if (CFStringGetCString (cf_str, &str[0], str.size(), encoding))<br>
+                {<br>
+                    str.resize(strlen(str.c_str())<wbr>);<br>
+                    return str.c_str();<br>
+                }<br>
+            }<br>
+        }<br>
+    }<br>
+    return NULL;<br>
+}<br>
+<br>
+// Static function that puts a copy of the file system representation of CF_STR<br>
+// into STR and returns the C string pointer that is contained in STR when<br>
+// successful, else NULL is returned. This allows the std::string parameter<br>
+// to own the extracted string, and also allows that string to be returned as<br>
+// a C string pointer that can be used.<br>
+<br>
+const char *<br>
+CFString::<wbr>FileSystemRepresentation (CFStringRef cf_str, std::string& str)<br>
+{<br>
+    if (cf_str)<br>
+    {<br>
+        CFIndex max_length = ::<wbr>CFStringGetMaximumSizeOfFileSy<wbr>stemRepresentation (cf_str);<br>
+        if (max_length > 0)<br>
+        {<br>
+            str.resize(max_length);<br>
+            if (!str.empty())<br>
+            {<br>
+                if (::<wbr>CFStringGetFileSystemRepresent<wbr>ation (cf_str, &str[0], str.size()))<br>
+                {<br>
+                    str.erase(::strlen(str.c_str()<wbr>));<br>
+                    return str.c_str();<br>
+                }<br>
+            }<br>
+        }<br>
+    }<br>
+    str.erase();<br>
+    return NULL;<br>
+}<br>
+<br>
+<br>
+CFIndex<br>
+CFString::GetLength() const<br>
+{<br>
+    CFStringRef str = get();<br>
+    if (str)<br>
+        return CFStringGetLength (str);<br>
+    return 0;<br>
+}<br>
+<br>
+<br>
+const char*<br>
+CFString::GlobPath(const char* path, std::string &expanded_path)<br>
+{<br>
+    glob_t globbuf;<br>
+    if (::glob (path, GLOB_TILDE, NULL, &globbuf) == 0)<br>
+    {<br>
+        expanded_path = globbuf.gl_pathv[0];<br>
+        ::globfree (&globbuf);<br>
+    }<br>
+    else<br>
+        expanded_path.clear();<br>
+<br>
+    return expanded_path.c_str();<br>
+}<br>
+<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFString.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/CFString.h?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>CFString.h?rev=280604&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFString.h (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFString.h Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,43 @@<br>
+//===-- CFString.h ------------------------------<wbr>----------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//  Created by Greg Clayton on 1/16/08.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef __CFString_h__<br>
+#define __CFString_h__<br>
+<br>
+#include "CFUtils.h"<br>
+#include <iosfwd><br>
+<br>
+class CFString : public CFReleaser<CFStringRef><br>
+{<br>
+public:<br>
+    //----------------------------<wbr>------------------------------<wbr>--------<br>
+    // Constructors and Destructors<br>
+    //----------------------------<wbr>------------------------------<wbr>--------<br>
+                        CFString (CFStringRef cf_str = NULL);<br>
+                        CFString (const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8);<br>
+                        CFString (const CFString& rhs);<br>
+                        CFString& operator= (const CFString& rhs);<br>
+                        virtual ~CFString ();<br>
+<br>
+        const char *    GetFileSystemRepresentation (std::string& str);<br>
+        CFStringRef     SetFileSystemRepresentation (const char *path);<br>
+        CFStringRef     SetFileSystemRepresentationFro<wbr>mCFType (CFTypeRef cf_type);<br>
+        CFStringRef     SetFileSystemRepresentationAnd<wbr>ExpandTilde (const char *path);<br>
+        const char *    UTF8 (std::string& str);<br>
+        CFIndex         GetLength() const;<br>
+        static const char *UTF8 (CFStringRef cf_str, std::string& str);<br>
+        static const char *FileSystemRepresentation (CFStringRef cf_str, std::string& str);<br>
+        static const char* GlobPath(const char* path, std::string &expanded_path);<br>
+};<br>
+<br>
+#endif // #ifndef __CFString_h__<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFUtils.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/CFUtils.h?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>CFUtils.h?rev=280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFUtils.h (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/CFUtils.h Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,81 @@<br>
+//===-- CFUtils.h ------------------------------<wbr>-----------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//  Created by Greg Clayton on 3/5/07.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef __CFUtils_h__<br>
+#define __CFUtils_h__<br>
+<br>
+#include <CoreFoundation/<wbr>CoreFoundation.h><br>
+<br>
+#ifdef __cplusplus<br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// Templatized CF helper class that can own any CF pointer and will<br>
+// call CFRelease() on any valid pointer it owns unless that pointer is<br>
+// explicitly released using the release() member function.<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+template <class T><br>
+class CFReleaser<br>
+{<br>
+public:<br>
+            // Type names for the avlue<br>
+            typedef T element_type;<br>
+<br>
+            // Constructors and destructors<br>
+            CFReleaser(T ptr = NULL) : _ptr(ptr) { }<br>
+            CFReleaser(const CFReleaser& copy) : _ptr(copy.get())<br>
+            {<br>
+                if (get())<br>
+                    ::CFRetain(get());<br>
+            }<br>
+            virtual ~CFReleaser() { reset(); }<br>
+<br>
+            // Assignments<br>
+            CFReleaser& operator= (const CFReleaser<T>& copy)<br>
+            {<br>
+                if (copy != *this)<br>
+                {<br>
+                    // Replace our owned pointer with the new one<br>
+                    reset(copy.get());<br>
+                    // Retain the current pointer that we own<br>
+                    if (get())<br>
+                        ::CFRetain(get());<br>
+                }<br>
+            }<br>
+            // Get the address of the contained type<br>
+            T *     ptr_address()   { return &_ptr; }<br>
+<br>
+            // Access the pointer itself<br>
+    const   T       get() const     { return _ptr;  }<br>
+            T       get()           { return _ptr;  }<br>
+<br>
+            // Set a new value for the pointer and CFRelease our old<br>
+            // value if we had a valid one.<br>
+            void    reset(T ptr = NULL)<br>
+                    {<br>
+                        if (ptr != _ptr)<br>
+                        {<br>
+                            if (_ptr != NULL)<br>
+                                ::CFRelease(_ptr);<br>
+                            _ptr = ptr;<br>
+                        }<br>
+                    }<br>
+<br>
+            // Release ownership without calling CFRelease<br>
+            T    release() { T tmp = _ptr; _ptr = NULL; return tmp; }<br>
+private:<br>
+    element_type _ptr;<br>
+};<br>
+<br>
+#endif    // #ifdef __cplusplus<br>
+#endif    // #ifndef __CFUtils_h__<br>
+<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>DarwinProcessLauncher.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>DarwinProcessLauncher.cpp?rev=<wbr>280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>DarwinProcessLauncher.cpp (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>DarwinProcessLauncher.cpp Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,737 @@<br>
+//<br>
+//  DarwinProcessLauncher.cpp<br>
+//  lldb<br>
+//<br>
+//  Created by Todd Fiala on 8/30/16.<br>
+//<br>
+//<br>
+<br>
+#include "DarwinProcessLauncher.h"<br>
+<br>
+// C includes<br>
+#include <spawn.h><br>
+#include <sys/ptrace.h><br>
+#include <sys/stat.h><br>
+#include <sys/sysctl.h><br>
+<br>
+#ifndef _POSIX_SPAWN_DISABLE_ASLR<br>
+#define _POSIX_SPAWN_DISABLE_ASLR       0x0100<br>
+#endif<br>
+<br>
+// LLDB includes<br>
+#include "lldb/lldb-enumerations.h"<br>
+<br>
+#include "lldb/Core/Error.h"<br>
+#include "lldb/Core/Log.h"<br>
+#include "lldb/Core/StreamString.h"<br>
+#include "lldb/Target/<wbr>ProcessLaunchInfo.h"<br>
+#include "lldb/Utility/PseudoTerminal.<wbr>h"<br>
+<br>
+#include "CFBundle.h"<br>
+#include "CFString.h"<br>
+<br>
+using namespace lldb;<br>
+using namespace lldb_private;<br>
+using namespace lldb_private::process_darwin;<br>
+using namespace lldb_private::darwin_process_<wbr>launcher;<br>
+<br>
+namespace<br>
+{<br>
+    static LaunchFlavor g_launch_flavor = LaunchFlavor::Default;<br>
+}<br>
+<br>
+namespace lldb_private<br>
+{<br>
+namespace darwin_process_launcher<br>
+{<br>
+<br>
+static uint32_t<br>
+GetCPUTypeForLocalProcess(::<wbr>pid_t pid)<br>
+{<br>
+    int mib[CTL_MAXNAME]={0,};<br>
+    size_t len = CTL_MAXNAME;<br>
+    if (::sysctlnametomib("sysctl.<wbr>proc_cputype", mib, &len))<br>
+        return 0;<br>
+<br>
+    mib[len] = pid;<br>
+    len++;<br>
+<br>
+    cpu_type_t cpu;<br>
+    size_t cpu_len = sizeof(cpu);<br>
+    if (::sysctl (mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0))<br>
+        cpu = 0;<br>
+    return cpu;<br>
+}<br>
+<br>
+static bool<br>
+ResolveExecutablePath(const char *path, char *resolved_path,<br>
+                      size_t resolved_path_size)<br>
+{<br>
+    if (path == NULL || path[0] == '\0')<br>
+        return false;<br>
+<br>
+    char max_path[PATH_MAX];<br>
+    std::string result;<br>
+    CFString::GlobPath(path, result);<br>
+<br>
+    if (result.empty())<br>
+        result = path;<br>
+<br>
+    struct stat path_stat;<br>
+    if (::stat(path, &path_stat) == 0)<br>
+    {<br>
+        if ((path_stat.st_mode & S_IFMT) == S_IFDIR)<br>
+        {<br>
+            CFBundle bundle(path);<br>
+            CFReleaser<CFURLRef> url(bundle.CopyExecutableURL ());<br>
+            if (url.get())<br>
+            {<br>
+                if (::<wbr>CFURLGetFileSystemRepresentati<wbr>on(url.get(), true,<br>
+                                                       (UInt8*)resolved_path,<br>
+                                                       resolved_path_size))<br>
+                    return true;<br>
+            }<br>
+        }<br>
+    }<br>
+<br>
+    if (realpath(path, max_path))<br>
+    {<br>
+        // Found the path relatively...<br>
+        ::strncpy(resolved_path, max_path, resolved_path_size);<br>
+        return strlen(resolved_path) + 1 < resolved_path_size;<br>
+    }<br>
+    else<br>
+    {<br>
+        // Not a relative path, check the PATH environment variable if the<br>
+        const char *PATH = getenv("PATH");<br>
+        if (PATH)<br>
+        {<br>
+            const char *curr_path_start = PATH;<br>
+            const char *curr_path_end;<br>
+            while (curr_path_start && *curr_path_start)<br>
+            {<br>
+                curr_path_end = strchr(curr_path_start, ':');<br>
+                if (curr_path_end == NULL)<br>
+                {<br>
+                    result.assign(curr_path_start)<wbr>;<br>
+                    curr_path_start = NULL;<br>
+                }<br>
+                else if (curr_path_end > curr_path_start)<br>
+                {<br>
+                    size_t len = curr_path_end - curr_path_start;<br>
+                    result.assign(curr_path_start, len);<br>
+                    curr_path_start += len + 1;<br>
+                }<br>
+                else<br>
+                    break;<br>
+<br>
+                result += '/';<br>
+                result += path;<br>
+                struct stat s;<br>
+                if (stat(result.c_str(), &s) == 0)<br>
+                {<br>
+                    ::strncpy(resolved_path, result.c_str(),<br>
+                              resolved_path_size);<br>
+                    return result.size() + 1 < resolved_path_size;<br>
+                }<br>
+            }<br>
+        }<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+// TODO check if we have a general purpose fork and exec.  We may be<br>
+// able to get rid of this entirely.<br>
+static Error<br>
+ForkChildForPTraceDebugging(<wbr>const char *path,<br>
+                            char const *argv[],<br>
+                            char const *envp[],<br>
+                            ::pid_t *pid,<br>
+                            int *pty_fd)<br>
+{<br>
+    Error error;<br>
+    if (!path || !argv || !envp || !pid || !pty_fd)<br>
+    {<br>
+        error.SetErrorString("invalid arguments");<br>
+        return error;<br>
+    }<br>
+<br>
+    // Use a fork that ties the child process's stdin/out/err to a pseudo<br>
+    // terminal so we can read it in our MachProcess::STDIOThread<br>
+    // as unbuffered io.<br>
+    lldb_utility::PseudoTerminal pty;<br>
+    char fork_error[256];<br>
+    memset(fork_error, 0, sizeof(fork_error));<br>
+    *pid = static_cast<::pid_t>(pty.Fork(<wbr>fork_error, sizeof(fork_error)));<br>
+    if (*pid < 0)<br>
+    {<br>
+        //----------------------------<wbr>------------------------------<wbr>----<br>
+        // Error during fork.<br>
+        //----------------------------<wbr>------------------------------<wbr>----<br>
+        *pid = static_cast<::pid_t>(LLDB_<wbr>INVALID_PROCESS_ID);<br>
+        error.<wbr>SetErrorStringWithFormat("%s()<wbr>: fork failed: %s",<br>
+                                       __FUNCTION__, fork_error);<br>
+        return error;<br>
+    }<br>
+    else if (pid == 0)<br>
+    {<br>
+        //----------------------------<wbr>------------------------------<wbr>----<br>
+        // Child process<br>
+        //----------------------------<wbr>------------------------------<wbr>----<br>
+<br>
+        // Debug this process.<br>
+        ::ptrace(PT_TRACE_ME, 0, 0, 0);<br>
+<br>
+        // Get BSD signals as mach exceptions.<br>
+        ::ptrace(PT_SIGEXC, 0, 0, 0);<br>
+<br>
+        // If our parent is setgid, lets make sure we don't inherit those<br>
+        // extra powers due to nepotism.<br>
+        if (::setgid(getgid()) == 0)<br>
+        {<br>
+            // Let the child have its own process group. We need to execute<br>
+            // this call in both the child and parent to avoid a race<br>
+            // condition between the two processes.<br>
+<br>
+            // Set the child process group to match its pid.<br>
+            ::setpgid(0, 0);<br>
+<br>
+            // Sleep a bit to before the exec call.<br>
+            ::sleep(1);<br>
+<br>
+            // Turn this process into the given executable.<br>
+            ::execv(path, (char * const *)argv);<br>
+        }<br>
+        // Exit with error code. Child process should have taken<br>
+        // over in above exec call and if the exec fails it will<br>
+        // exit the child process below.<br>
+        ::exit(127);<br>
+    }<br>
+    else<br>
+    {<br>
+        //----------------------------<wbr>------------------------------<wbr>----<br>
+        // Parent process<br>
+        //----------------------------<wbr>------------------------------<wbr>----<br>
+        // Let the child have its own process group. We need to execute<br>
+        // this call in both the child and parent to avoid a race condition<br>
+        // between the two processes.<br>
+<br>
+        // Set the child process group to match its pid<br>
+        ::setpgid(*pid, *pid);<br>
+        if (pty_fd)<br>
+        {<br>
+            // Release our master pty file descriptor so the pty class doesn't<br>
+            // close it and so we can continue to use it in our STDIO thread<br>
+            *pty_fd = pty.<wbr>ReleaseMasterFileDescriptor();<br>
+        }<br>
+    }<br>
+    return error;<br>
+}<br>
+<br>
+static Error<br>
+CreatePosixSpawnFileAction(<wbr>const FileAction &action,<br>
+                           posix_spawn_file_actions_t *file_actions)<br>
+{<br>
+    Error error;<br>
+<br>
+    // Log it.<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+    if (log)<br>
+    {<br>
+        StreamString stream;<br>
+        stream.PutCString("converting file action for posix_spawn(): ");<br>
+        action.Dump(stream);<br>
+        stream.Flush();<br>
+        log->PutCString(stream.<wbr>GetString().c_str());<br>
+    }<br>
+<br>
+    // Validate args.<br>
+    if (!file_actions)<br>
+    {<br>
+        error.SetErrorString("<wbr>mandatory file_actions arg is null");<br>
+        return error;<br>
+    }<br>
+<br>
+    // Build the posix file action.<br>
+    switch (action.GetAction())<br>
+    {<br>
+        case FileAction::eFileActionOpen:<br>
+        {<br>
+            const int error_code =<br>
+                ::posix_spawn_file_actions_<wbr>addopen(file_actions,<br>
+                                                   action.GetFD(),<br>
+                                                   action.GetPath(),<br>
+                                                   action.GetActionArgument(),<br>
+                                                   0);<br>
+            if (error_code != 0)<br>
+            {<br>
+                error.SetError(error_code, eErrorTypePOSIX);<br>
+                return error;<br>
+            }<br>
+            break;<br>
+        }<br>
+<br>
+        case FileAction::eFileActionClose:<br>
+        {<br>
+            const int error_code =<br>
+            ::posix_spawn_file_actions_<wbr>addclose(file_actions,<br>
+                                                action.GetFD());<br>
+            if (error_code != 0)<br>
+            {<br>
+                error.SetError(error_code, eErrorTypePOSIX);<br>
+                return error;<br>
+            }<br>
+            break;<br>
+        }<br>
+<br>
+        case FileAction::<wbr>eFileActionDuplicate:<br>
+        {<br>
+            const int error_code =<br>
+            ::posix_spawn_file_actions_<wbr>adddup2(file_actions,<br>
+                                               action.GetFD(),<br>
+                                               action.GetActionArgument());<br>
+            if (error_code != 0)<br>
+            {<br>
+                error.SetError(error_code, eErrorTypePOSIX);<br>
+                return error;<br>
+            }<br>
+            break;<br>
+        }<br>
+<br>
+        case FileAction::eFileActionNone:<br>
+        default:<br>
+            if (log)<br>
+                log->Printf("%s(): unsupported file action %u",<br>
+                            __FUNCTION__, action.GetAction());<br>
+            break;<br>
+    }<br>
+<br>
+    return error;<br>
+}<br>
+<br>
+static Error<br>
+<wbr>PosixSpawnChildForPTraceDebugg<wbr>ing(const char *path,<br>
+                                  ProcessLaunchInfo &launch_info,<br>
+                                  ::pid_t *pid,<br>
+                                  cpu_type_t *actual_cpu_type)<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    if (!pid)<br>
+    {<br>
+        error.<wbr>SetErrorStringWithFormat("%s()<wbr>: pid arg cannot be null",<br>
+                                       __FUNCTION__);<br>
+        return error;<br>
+    }<br>
+<br>
+    posix_spawnattr_t attr;<br>
+    short flags;<br>
+    if (log)<br>
+    {<br>
+        StreamString stream;<br>
+        stream.Printf("%s(path='%s',..<wbr>.)\n", __FUNCTION__, path);<br>
+        launch_info.Dump(stream, nullptr);<br>
+        stream.Flush();<br>
+        log->PutCString(stream.<wbr>GetString().c_str());<br>
+    }<br>
+<br>
+    int error_code;<br>
+    if ((error_code = ::posix_spawnattr_init(&attr)) != 0)<br>
+    {<br>
+        if (log)<br>
+            log->Printf("::posix_<wbr>spawnattr_init(&attr) failed");<br>
+        error.SetError(error_code, eErrorTypePOSIX);<br>
+        return error;<br>
+    }<br>
+<br>
+    // Ensure we clean up the spawnattr structure however we exit this<br>
+    // function.<br>
+    std::unique_ptr<posix_<wbr>spawnattr_t, int(*)(posix_spawnattr_t*)><br>
+        spawnattr_up(&attr, ::posix_spawnattr_destroy);<br>
+<br>
+<br>
+    flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETSIGDEF |<br>
+        POSIX_SPAWN_SETSIGMASK;<br>
+    if (launch_info.GetFlags().Test(<wbr>eLaunchFlagDisableASLR))<br>
+        flags |= _POSIX_SPAWN_DISABLE_ASLR;<br>
+<br>
+    sigset_t no_signals;<br>
+    sigset_t all_signals;<br>
+    sigemptyset (&no_signals);<br>
+    sigfillset (&all_signals);<br>
+    ::posix_spawnattr_setsigmask(&<wbr>attr, &no_signals);<br>
+    ::posix_spawnattr_<wbr>setsigdefault(&attr, &all_signals);<br>
+<br>
+    if ((error_code = ::posix_spawnattr_setflags(&<wbr>attr, flags)) != 0)<br>
+    {<br>
+        if (log)<br>
+            log->Printf("::posix_<wbr>spawnattr_setflags(&attr, "<br>
+                        "POSIX_SPAWN_START_SUSPENDED%<wbr>s) failed: %s",<br>
+                        flags & _POSIX_SPAWN_DISABLE_ASLR ?<br>
+                        " | _POSIX_SPAWN_DISABLE_ASLR" : "",<br>
+                        strerror(error_code));<br>
+        error.SetError(error_code, eErrorTypePOSIX);<br>
+        return error;<br>
+    }<br>
+<br>
+#if !defined(__arm__)<br>
+<br>
+    // We don't need to do this for ARM, and we really shouldn't now that we<br>
+    // have multiple CPU subtypes and no posix_spawnattr call that allows us<br>
+    // to set which CPU subtype to launch...<br>
+    cpu_type_t desired_cpu_type =<br>
+        launch_info.GetArchitecture().<wbr>GetMachOCPUType();<br>
+    if (desired_cpu_type != LLDB_INVALID_CPUTYPE)<br>
+    {<br>
+        size_t ocount = 0;<br>
+        error_code = ::posix_spawnattr_setbinpref_<wbr>np(&attr, 1,<br>
+                                                     &desired_cpu_type,<br>
+                                                     &ocount);<br>
+        if (error_code != 0)<br>
+        {<br>
+            if (log)<br>
+                log->Printf("::posix_<wbr>spawnattr_setbinpref_np(&attr, 1, "<br>
+                            "cpu_type = 0x%8.8x, count => %llu): %s",<br>
+                            desired_cpu_type, (uint64_t)ocount,<br>
+                            strerror(error_code));<br>
+            error.SetError(error_code, eErrorTypePOSIX);<br>
+            return error;<br>
+        }<br>
+        if (ocount != 1)<br>
+        {<br>
+            error.<wbr>SetErrorStringWithFormat("<wbr>posix_spawnattr_setbinpref_np "<br>
+                                           "did not set the expected number "<br>
+                                           "of cpu_type entries: expected 1 "<br>
+                                           "but was %zu", ocount);<br>
+            return error;<br>
+        }<br>
+    }<br>
+#endif<br>
+<br>
+    posix_spawn_file_actions_t file_actions;<br>
+    if ((error_code = ::posix_spawn_file_actions_<wbr>init(&file_actions)) != 0)<br>
+    {<br>
+        if (log)<br>
+            log->Printf("::posix_spawn_<wbr>file_actions_init(&file_<wbr>actions) "<br>
+                        "failed: %s",<br>
+                        strerror(error_code));<br>
+        error.SetError(error_code, eErrorTypePOSIX);<br>
+        return error;<br>
+    }<br>
+<br>
+    // Ensure we clean up file actions however we exit this.  When the<br>
+    // file_actions_up below goes out of scope, we'll get our file action<br>
+    // cleanup.<br>
+    std::unique_ptr<posix_spawn_<wbr>file_actions_t,<br>
+                    int(*)(posix_spawn_file_<wbr>actions_t*)><br>
+        file_actions_up(&file_actions, ::posix_spawn_file_actions_<wbr>destroy);<br>
+<br>
+    // We assume the caller has setup the file actions appropriately.  We<br>
+    // are not in the business of figuring out what we really need here.<br>
+    // lldb-server will have already called FinalizeFileActions() as well<br>
+    // to button these up properly.<br>
+    const size_t num_actions = launch_info.GetNumFileActions(<wbr>);<br>
+    for (size_t action_index = 0; action_index < num_actions; ++action_index)<br>
+    {<br>
+        const FileAction *const action =<br>
+            launch_info.<wbr>GetFileActionAtIndex(action_<wbr>index);<br>
+        if (!action)<br>
+            continue;<br>
+<br>
+        error = CreatePosixSpawnFileAction(*<wbr>action, &file_actions);<br>
+        if (!error.Success())<br>
+        {<br>
+            if (log)<br>
+                log->Printf("%s(): error converting FileAction to posix_spawn "<br>
+                            "file action: %s", __FUNCTION__, error.AsCString());<br>
+            return error;<br>
+        }<br>
+    }<br>
+<br>
+    // TODO: Verify if we can set the working directory back immediately<br>
+    // after the posix_spawnp call without creating a race condition???<br>
+    const char *const working_directory =<br>
+        launch_info.<wbr>GetWorkingDirectory().<wbr>GetCString();<br>
+    if (working_directory && working_directory[0])<br>
+        ::chdir(working_directory);<br>
+<br>
+    auto argv = launch_info.GetArguments().<wbr>GetArgumentVector();<br>
+    auto envp = launch_info.<wbr>GetEnvironmentEntries().<wbr>GetArgumentVector();<br>
+    error_code = ::posix_spawnp(pid, path, &file_actions, &attr,<br>
+                                (char * const*)argv, (char * const*)envp);<br>
+    if (error_code != 0)<br>
+    {<br>
+        if (log)<br>
+            log->Printf("::posix_spawnp(<wbr>pid => %p, path = '%s', file_actions "<br>
+                        "= %p, attr = %p, argv = %p, envp = %p) failed: %s",<br>
+                        pid, path, &file_actions, &attr, argv, envp,<br>
+                        strerror(error_code));<br>
+        error.SetError(error_code, eErrorTypePOSIX);<br>
+        return error;<br>
+    }<br>
+<br>
+    // Validate we got a pid.<br>
+    if (pid == LLDB_INVALID_PROCESS_ID)<br>
+    {<br>
+        error.SetErrorString("posix_<wbr>spawn() did not indicate a failure but it "<br>
+                             "failed to return a pid, aborting.");<br>
+        return error;<br>
+    }<br>
+<br>
+    if (actual_cpu_type)<br>
+    {<br>
+        *actual_cpu_type = GetCPUTypeForLocalProcess(*<wbr>pid);<br>
+        if (log)<br>
+            log->Printf("%s(): cpu type for launched process pid=%i: "<br>
+                        "cpu_type=0x%8.8x", __FUNCTION__, *pid,<br>
+                        *actual_cpu_type);<br>
+    }<br>
+<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+LaunchInferior(<wbr>ProcessLaunchInfo &launch_info, int *pty_master_fd,<br>
+               LaunchFlavor *launch_flavor)<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    if (!launch_flavor)<br>
+    {<br>
+        error.SetErrorString("<wbr>mandatory launch_flavor field was null");<br>
+        return error;<br>
+    }<br>
+<br>
+    if (log)<br>
+    {<br>
+        StreamString stream;<br>
+        stream.Printf("<wbr>NativeProcessDarwin::%s(): launching with the "<br>
+                      "following launch info:", __FUNCTION__);<br>
+        launch_info.Dump(stream, nullptr);<br>
+        stream.Flush();<br>
+        log->PutCString(stream.<wbr>GetString().c_str());<br>
+    }<br>
+<br>
+    // Retrieve the binary name given to us.<br>
+    char given_path[PATH_MAX];<br>
+    given_path[0] = '\0';<br>
+    launch_info.GetExecutableFile(<wbr>).GetPath(given_path, sizeof(given_path));<br>
+<br>
+    // Determine the manner in which we'll launch.<br>
+    *launch_flavor = g_launch_flavor;<br>
+    if (*launch_flavor == LaunchFlavor::Default)<br>
+    {<br>
+        // Our default launch method is posix spawn<br>
+        *launch_flavor = LaunchFlavor::PosixSpawn;<br>
+#if defined WITH_FBS<br>
+        // Check if we have an app bundle, if so launch using BackBoard Services.<br>
+        if (strstr(given_path, ".app"))<br>
+        {<br>
+            *launch_flavor = eLaunchFlavorFBS;<br>
+        }<br>
+#elif defined WITH_BKS<br>
+        // Check if we have an app bundle, if so launch using BackBoard Services.<br>
+        if (strstr(given_path, ".app"))<br>
+        {<br>
+            *launch_flavor = eLaunchFlavorBKS;<br>
+        }<br>
+#elif defined WITH_SPRINGBOARD<br>
+        // Check if we have an app bundle, if so launch using SpringBoard.<br>
+        if (strstr(given_path, ".app"))<br>
+        {<br>
+            *launch_flavor = eLaunchFlavorSpringBoard;<br>
+        }<br>
+#endif<br>
+    }<br>
+<br>
+    // Attempt to resolve the binary name to an absolute path.<br>
+    char resolved_path[PATH_MAX];<br>
+    resolved_path[0] = '\0';<br>
+<br>
+    if (log)<br>
+        log->Printf("%s(): attempting to resolve given binary path: \"%s\"",<br>
+                    __FUNCTION__, given_path);<br>
+<br>
+    // If we fail to resolve the path to our executable, then just use what we<br>
+    // were given and hope for the best<br>
+    if (!ResolveExecutablePath(given_<wbr>path, resolved_path,<br>
+                               sizeof(resolved_path)) )<br>
+    {<br>
+        if (log)<br>
+            log->Printf("%s(): failed to resolve binary path, using "<br>
+                        "what was given verbatim and hoping for the best",<br>
+                        __FUNCTION__);<br>
+        ::strncpy(resolved_path, given_path,<br>
+                  sizeof(resolved_path));<br>
+    }<br>
+    else<br>
+    {<br>
+        if (log)<br>
+            log->Printf("%s(): resolved given binary path to: \"%s\"",<br>
+                        __FUNCTION__, resolved_path);<br>
+    }<br>
+<br>
+    char launch_err_str[PATH_MAX];<br>
+    launch_err_str[0] = '\0';<br>
+<br>
+    // TODO figure out how to handle QSetProcessEvent<br>
+    // const char *process_event = ctx.GetProcessEvent();<br>
+<br>
+    // Ensure the binary is there.<br>
+    struct stat path_stat;<br>
+    if (::stat(resolved_path, &path_stat) == -1)<br>
+    {<br>
+        error.SetErrorToErrno();<br>
+        return error;<br>
+    }<br>
+<br>
+    // Fork a child process for debugging<br>
+    // state_callback(<wbr>eStateLaunching);<br>
+<br>
+    const auto argv = launch_info.GetArguments().<wbr>GetConstArgumentVector();<br>
+    const auto envp =<br>
+        launch_info.<wbr>GetEnvironmentEntries().<wbr>GetConstArgumentVector();<br>
+<br>
+    switch (*launch_flavor)<br>
+    {<br>
+        case LaunchFlavor::ForkExec:<br>
+        {<br>
+            ::pid_t pid = LLDB_INVALID_PROCESS_ID;<br>
+            error = ForkChildForPTraceDebugging(<wbr>resolved_path, argv, envp,<br>
+                                                &pid, pty_master_fd);<br>
+            if (error.Success())<br>
+            {<br>
+                launch_info.SetProcessID(<wbr>static_cast<lldb::pid_t>(pid))<wbr>;<br>
+            }<br>
+            else<br>
+            {<br>
+                // Reset any variables that might have been set during a failed<br>
+                // launch attempt.<br>
+                if (pty_master_fd)<br>
+                    *pty_master_fd = -1;<br>
+<br>
+                // We're done.<br>
+                return error;<br>
+            }<br>
+        }<br>
+            break;<br>
+<br>
+#ifdef WITH_FBS<br>
+        case LaunchFlavor::FBS:<br>
+        {<br>
+            const char *app_ext = strstr(path, ".app");<br>
+            if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/'))<br>
+            {<br>
+                std::string app_bundle_path(path, app_ext + strlen(".app"));<br>
+                m_flags |= eMachProcessFlagsUsingFBS;<br>
+                if (BoardServiceLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, event_data, launch_err) != 0)<br>
+                    return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid.<br>
+                else<br>
+                    break; // We tried a FBS launch, but didn't succeed lets get out<br>
+            }<br>
+        }<br>
+            break;<br>
+#endif<br>
+<br>
+#ifdef WITH_BKS<br>
+        case LaunchFlavor::BKS:<br>
+        {<br>
+            const char *app_ext = strstr(path, ".app");<br>
+            if (app_ext && (app_ext[4] == '\0' || app_ext[4] == '/'))<br>
+            {<br>
+                std::string app_bundle_path(path, app_ext + strlen(".app"));<br>
+                m_flags |= eMachProcessFlagsUsingBKS;<br>
+                if (BoardServiceLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, event_data, launch_err) != 0)<br>
+                    return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid.<br>
+                else<br>
+                    break; // We tried a BKS launch, but didn't succeed lets get out<br>
+            }<br>
+        }<br>
+            break;<br>
+#endif<br>
+<br>
+#ifdef WITH_SPRINGBOARD<br>
+        case LaunchFlavor::SpringBoard:<br>
+        {<br>
+            //  .../whatever.app/whatever ?<br>
+            //  Or .../com.apple.whatever.app/<wbr>whatever -- be careful of ".app" in "com.apple.whatever" here<br>
+            const char *app_ext = strstr (path, ".app/");<br>
+            if (app_ext == NULL)<br>
+            {<br>
+                // .../whatever.app ?<br>
+                int len = strlen (path);<br>
+                if (len > 5)<br>
+                {<br>
+                    if (strcmp (path + len - 4, ".app") == 0)<br>
+                    {<br>
+                        app_ext = path + len - 4;<br>
+                    }<br>
+                }<br>
+            }<br>
+            if (app_ext)<br>
+            {<br>
+                std::string app_bundle_path(path, app_ext + strlen(".app"));<br>
+                if (SBLaunchForDebug (app_bundle_path.c_str(), argv, envp, no_stdio, disable_aslr, launch_err) != 0)<br>
+                    return m_pid; // A successful SBLaunchForDebug() returns and assigns a non-zero m_pid.<br>
+                else<br>
+                    break; // We tried a springboard launch, but didn't succeed lets get out<br>
+            }<br>
+        }<br>
+            break;<br>
+#endif<br>
+<br>
+        case LaunchFlavor::PosixSpawn:<br>
+        {<br>
+            ::pid_t pid = LLDB_INVALID_PROCESS_ID;<br>
+<br>
+            // Retrieve paths for stdin/stdout/stderr.<br>
+            cpu_type_t actual_cpu_type = 0;<br>
+            error = PosixSpawnChildForPTraceDebugg<wbr>ing(resolved_path,<br>
+                                                      launch_info,<br>
+                                                      &pid,<br>
+                                                      &actual_cpu_type);<br>
+            if (error.Success())<br>
+            {<br>
+                launch_info.SetProcessID(<wbr>static_cast<lldb::pid_t>(pid))<wbr>;<br>
+                if (pty_master_fd)<br>
+                    *pty_master_fd = launch_info.GetPTY().<br>
+                        ReleaseMasterFileDescriptor();<br>
+            }<br>
+            else<br>
+            {<br>
+                // Reset any variables that might have been set during a failed<br>
+                // launch attempt.<br>
+                if (pty_master_fd)<br>
+                    *pty_master_fd = -1;<br>
+<br>
+                // We're done.<br>
+                return error;<br>
+            }<br>
+            break;<br>
+        }<br>
+<br>
+        default:<br>
+            // Invalid launch flavor.<br>
+            error.<wbr>SetErrorStringWithFormat("<wbr>NativeProcessDarwin::%s(): unknown "<br>
+                                           "launch flavor %d", __FUNCTION__,<br>
+                                           (int)*launch_flavor);<br>
+            return error;<br>
+    }<br>
+<br>
+    if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID)<br>
+    {<br>
+        // If we don't have a valid process ID and no one has set the error,<br>
+        // then return a generic error.<br>
+        if (error.Success())<br>
+            error.<wbr>SetErrorStringWithFormat("%s()<wbr>: failed to launch, no reason "<br>
+                                           "specified", __FUNCTION__);<br>
+    }<br>
+<br>
+    // We're done with the launch side of the operation.<br>
+    return error;<br>
+}<br>
+<br>
+}} // namespaces<br>
+<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>DarwinProcessLauncher.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/DarwinProcessLauncher.h?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>DarwinProcessLauncher.h?rev=<wbr>280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>DarwinProcessLauncher.h (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>DarwinProcessLauncher.h Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,51 @@<br>
+//===-- DarwinProcessLauncher.h ------------------------------<wbr>---*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef DarwinProcessLauncher_h<br>
+#define DarwinProcessLauncher_h<br>
+<br>
+// C headers<br>
+#include <mach/machine.h><br>
+#include <sys/types.h><br>
+<br>
+// C++ headers<br>
+#include <functional><br>
+<br>
+// LLDB headers<br>
+#include "lldb/lldb-enumerations.h"<br>
+#include "lldb/lldb-forward.h"<br>
+<br>
+#include "LaunchFlavor.h"<br>
+<br>
+namespace lldb_private<br>
+{<br>
+namespace darwin_process_launcher<br>
+{<br>
+// ==============================<wbr>==============================<wbr>=================<br>
+/// Launches a process for debugging.<br>
+///<br>
+/// @param[inout] launch_info<br>
+///     Specifies details about the process to launch (e.g. path, architecture,<br>
+///     etc.).  On output, includes the launched ProcessID (pid).<br>
+///<br>
+/// @param[out] pty_master_fd<br>
+///     Returns the master side of the pseudo-terminal used to communicate<br>
+///     with stdin/stdout from the launched process.  May be nullptr.<br>
+///<br>
+/// @param[out] launch_flavor<br>
+///     Contains the launch flavor used when launching the process.<br>
+// ==============================<wbr>==============================<wbr>=================<br>
+Error<br>
+LaunchInferior(<wbr>ProcessLaunchInfo &launch_info, int *pty_master_fd,<br>
+               lldb_private::process_darwin::<wbr>LaunchFlavor *launch_flavor);<br>
+<br>
+} // darwin_process_launcher<br>
+} // lldb_private<br>
+<br>
+#endif /* DarwinProcessLauncher_h */<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/LaunchFlavor.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/LaunchFlavor.h?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>LaunchFlavor.h?rev=280604&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/LaunchFlavor.h (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/LaunchFlavor.h Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,34 @@<br>
+//===-- LaunchFlavor.h ------------------------------<wbr>---------- -*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LaunchFlavor_h<br>
+#define LaunchFlavor_h<br>
+<br>
+namespace lldb_private {<br>
+namespace process_darwin {<br>
+<br>
+enum class LaunchFlavor<br>
+{<br>
+    Default = 0,<br>
+    PosixSpawn = 1,<br>
+    ForkExec = 2,<br>
+#ifdef WITH_SPRINGBOARD<br>
+    SpringBoard = 3,<br>
+#endif<br>
+#ifdef WITH_BKS<br>
+    BKS = 4,<br>
+#endif<br>
+#ifdef WITH_FBS<br>
+    FBS = 5<br>
+#endif<br>
+};<br>
+<br>
+}} // namespaces<br>
+<br>
+#endif /* LaunchFlavor_h */<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/MachException.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/MachException.cpp?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>MachException.cpp?rev=280604&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/MachException.<wbr>cpp (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/MachException.<wbr>cpp Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,684 @@<br>
+//===-- MachException.cpp ------------------------------<wbr>---------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//  Created by Greg Clayton on 6/18/07.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "MachException.h"<br>
+<br>
+// C includes<br>
+#include <errno.h><br>
+#include <sys/types.h><br>
+#include <sys/ptrace.h><br>
+<br>
+// C++ includes<br>
+#include <mutex><br>
+<br>
+// LLDB includes<br>
+#include "lldb/Core/Error.h"<br>
+#include "lldb/Core/Log.h"<br>
+#include "lldb/Core/Stream.h"<br>
+#include "lldb/Target/UnixSignals.h"<br>
+#include "lldb/Utility/LLDBAssert.h"<br>
+<br>
+using namespace lldb;<br>
+using namespace lldb_private;<br>
+using namespace lldb_private::process_darwin;<br>
+<br>
+// Routine mach_exception_raise<br>
+extern "C"<br>
+kern_return_t catch_mach_exception_raise<br>
+(<br>
+    mach_port_t exception_port,<br>
+    mach_port_t thread,<br>
+    mach_port_t task,<br>
+    exception_type_t exception,<br>
+    mach_exception_data_t code,<br>
+    mach_msg_type_number_t codeCnt<br>
+);<br>
+<br>
+extern "C"<br>
+kern_return_t catch_mach_exception_raise_<wbr>state<br>
+(<br>
+    mach_port_t exception_port,<br>
+    exception_type_t exception,<br>
+    const mach_exception_data_t code,<br>
+    mach_msg_type_number_t codeCnt,<br>
+    int *flavor,<br>
+    const thread_state_t old_state,<br>
+    mach_msg_type_number_t old_stateCnt,<br>
+    thread_state_t new_state,<br>
+    mach_msg_type_number_t *new_stateCnt<br>
+);<br>
+<br>
+// Routine mach_exception_raise_state_<wbr>identity<br>
+extern "C"<br>
+kern_return_t catch_mach_exception_raise_<wbr>state_identity<br>
+(<br>
+    mach_port_t exception_port,<br>
+    mach_port_t thread,<br>
+    mach_port_t task,<br>
+    exception_type_t exception,<br>
+    mach_exception_data_t code,<br>
+    mach_msg_type_number_t codeCnt,<br>
+    int *flavor,<br>
+    thread_state_t old_state,<br>
+    mach_msg_type_number_t old_stateCnt,<br>
+    thread_state_t new_state,<br>
+    mach_msg_type_number_t *new_stateCnt<br>
+);<br>
+<br>
+extern "C" boolean_t mach_exc_server(<br>
+        mach_msg_header_t *InHeadP,<br>
+        mach_msg_header_t *OutHeadP);<br>
+<br>
+// Any access to the g_message variable should be done by locking the<br>
+// g_message_mutex first, using the g_message variable, then unlocking<br>
+// the g_message_mutex. See MachException::Message::<wbr>CatchExceptionRaise()<br>
+// for sample code.<br>
+<br>
+static MachException::Data *g_message = NULL;<br>
+<br>
+<br>
+extern "C"<br>
+kern_return_t<br>
+catch_mach_exception_raise_<wbr>state<br>
+(<br>
+    mach_port_t                 exc_port,<br>
+    exception_type_t            exc_type,<br>
+    const mach_exception_data_t exc_data,<br>
+    mach_msg_type_number_t      exc_data_count,<br>
+    int *                       flavor,<br>
+    const thread_state_t        old_state,<br>
+    mach_msg_type_number_t      old_stateCnt,<br>
+    thread_state_t              new_state,<br>
+    mach_msg_type_number_t *    new_stateCnt<br>
+)<br>
+{<br>
+    // TODO change to LIBLLDB_LOG_EXCEPTION<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+    if (log)<br>
+    {<br>
+        log->Printf("::%s(exc_port = 0x%4.4x, exc_type = %d (%s), "<br>
+                    "exc_data = 0x%llx, exc_data_count = %d)",<br>
+                        __FUNCTION__, exc_port, exc_type,<br>
+                    MachException::Name(exc_type), (uint64_t)exc_data,<br>
+                    exc_data_count);<br>
+    }<br>
+    return KERN_FAILURE;<br>
+}<br>
+<br>
+extern "C"<br>
+kern_return_t<br>
+catch_mach_exception_raise_<wbr>state_identity<br>
+(<br>
+    mach_port_t             exc_port,<br>
+    mach_port_t             thread_port,<br>
+    mach_port_t             task_port,<br>
+    exception_type_t        exc_type,<br>
+    mach_exception_data_t   exc_data,<br>
+    mach_msg_type_number_t  exc_data_count,<br>
+    int *                   flavor,<br>
+    thread_state_t          old_state,<br>
+    mach_msg_type_number_t  old_stateCnt,<br>
+    thread_state_t          new_state,<br>
+    mach_msg_type_number_t *new_stateCnt<br>
+)<br>
+{<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+    if (log)<br>
+    {<br>
+        log->Printf("::%s(exc_port = 0x%4.4x, thd_port = 0x%4.4x, "<br>
+                    "tsk_port = 0x%4.4x, exc_type = %d (%s), exc_data[%d] = "<br>
+                    "{ 0x%llx, 0x%llx })", __FUNCTION__, exc_port, thread_port,<br>
+                    task_port, exc_type, MachException::Name(exc_type),<br>
+                    exc_data_count,<br>
+                    (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD),<br>
+                    (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD));<br>
+    }<br>
+    mach_port_deallocate (mach_task_self(), task_port);<br>
+    mach_port_deallocate (mach_task_self(), thread_port);<br>
+<br>
+    return KERN_FAILURE;<br>
+}<br>
+<br>
+extern "C"<br>
+kern_return_t<br>
+catch_mach_exception_raise<br>
+(<br>
+    mach_port_t             exc_port,<br>
+    mach_port_t             thread_port,<br>
+    mach_port_t             task_port,<br>
+    exception_type_t        exc_type,<br>
+    mach_exception_data_t   exc_data,<br>
+    mach_msg_type_number_t  exc_data_count)<br>
+{<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+    if (log)<br>
+    {<br>
+        log->Printf("::%s(exc_port = 0x%4.4x, thd_port = 0x%4.4x, "<br>
+                    "tsk_port = 0x%4.4x, exc_type = %d (%s), exc_data[%d] "<br>
+                    "= { 0x%llx, 0x%llx })", __FUNCTION__, exc_port,<br>
+                    thread_port, task_port, exc_type,<br>
+                    MachException::Name(exc_type), exc_data_count,<br>
+                    (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD),<br>
+                    (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD));<br>
+    }<br>
+<br>
+    if (task_port == g_message->task_port)<br>
+    {<br>
+        g_message->task_port = task_port;<br>
+        g_message->thread_port = thread_port;<br>
+        g_message->exc_type = exc_type;<br>
+        g_message->exc_data.resize(<wbr>exc_data_count);<br>
+        ::memcpy(&g_message->exc_data[<wbr>0], exc_data,<br>
+                 g_message->exc_data.size() *<br>
+                 sizeof (mach_exception_data_type_t));<br>
+        return KERN_SUCCESS;<br>
+    }<br>
+    return KERN_FAILURE;<br>
+}<br>
+<br>
+#if 0<br>
+void<br>
+MachException::Message::Dump(<wbr>Stream &stream) const<br>
+{<br>
+    stream.Printf("exc_msg { bits = 0x%8.8x size = 0x%8.8x remote-port = "<br>
+                  "0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x "<br>
+                  "id = 0x%8.8x }\n",<br>
+        exc_msg.hdr.msgh_bits,<br>
+        exc_msg.hdr.msgh_size,<br>
+        exc_msg.hdr.msgh_remote_port,<br>
+        exc_msg.hdr.msgh_local_port,<br>
+        exc_msg.hdr.msgh_reserved,<br>
+        exc_msg.hdr.msgh_id);<br>
+<br>
+    stream.Printf("reply_msg { bits = 0x%8.8x size = 0x%8.8x remote-port "<br>
+                  "= 0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x "<br>
+                  "id = 0x%8.8x }",<br>
+                  reply_msg.hdr.msgh_bits,<br>
+                  reply_msg.hdr.msgh_size,<br>
+                  reply_msg.hdr.msgh_remote_<wbr>port,<br>
+                  reply_msg.hdr.msgh_local_port,<br>
+                  reply_msg.hdr.msgh_reserved,<br>
+                  reply_msg.hdr.msgh_id);<br>
+    stream.Flush();<br>
+}<br>
+#endif<br>
+<br>
+bool<br>
+MachException::Data::<wbr>GetStopInfo(struct ThreadStopInfo *stop_info,<br>
+                                 const UnixSignals &signals,<br>
+                                 Stream &stream) const<br>
+{<br>
+    if (!stop_info)<br>
+        return false;<br>
+<br>
+    // Zero out the structure.<br>
+    memset(stop_info, 0, sizeof(struct ThreadStopInfo));<br>
+<br>
+    if (exc_type == 0)<br>
+    {<br>
+        stop_info->reason = eStopReasonInvalid;<br>
+        return true;<br>
+    }<br>
+<br>
+    // We always stop with a mach exception.<br>
+    stop_info->reason = eStopReasonException;<br>
+    // Save the EXC_XXXX exception type.<br>
+    stop_info->details.exception.<wbr>type = exc_type;<br>
+<br>
+    // Fill in a text description<br>
+    const char * exc_name = MachException::Name(exc_type);<br>
+    if (exc_name)<br>
+        stream.Printf("%s", exc_name);<br>
+    else<br>
+        stream.Printf("%i", exc_type);<br>
+<br>
+    stop_info->details.exception.<wbr>data_count = exc_data.size();<br>
+<br>
+    int soft_signal = SoftSignal();<br>
+    if (soft_signal)<br>
+    {<br>
+        const char *sig_str = signals.GetSignalAsCString(<wbr>soft_signal);<br>
+        stream.Printf(" EXC_SOFT_SIGNAL( %i ( %s ))", soft_signal,<br>
+                      sig_str ? sig_str : "unknown signal");<br>
+    }<br>
+    else<br>
+    {<br>
+        // No special disassembly for exception data, just print it.<br>
+        size_t idx;<br>
+        stream.Printf(" data[%llu] = {",<br>
+                      (uint64_t)stop_info->details.<wbr>exception.data_count);<br>
+<br>
+        for (idx = 0; idx < stop_info->details.exception.<wbr>data_count; ++idx)<br>
+        {<br>
+            stream.Printf("0x%llx%c", (uint64_t)exc_data[idx],<br>
+                          ((idx + 1 == stop_info->details.exception.<wbr>data_count)<br>
+                           ? '}' : ','));<br>
+        }<br>
+    }<br>
+<br>
+    // Copy the exception data<br>
+    for (size_t i = 0; i < stop_info->details.exception.<wbr>data_count; i++)<br>
+        stop_info->details.exception.<wbr>data[i] = exc_data[i];<br>
+<br>
+    return true;<br>
+}<br>
+<br>
+Error<br>
+MachException::Message::<wbr>Receive(mach_port_t port, mach_msg_option_t options,<br>
+                                mach_msg_timeout_t timeout,<br>
+                                mach_port_t notify_port)<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+<br>
+    mach_msg_timeout_t mach_msg_timeout =<br>
+        options & MACH_RCV_TIMEOUT ? timeout : 0;<br>
+    if (log && ((options & MACH_RCV_TIMEOUT) == 0))<br>
+    {<br>
+        // Dump this log message if we have no timeout in case it never returns<br>
+        log->Printf("::mach_msg(msg->{<wbr>bits = %#x, size = %u remote_port = %#x, "<br>
+                    "local_port = %#x, reserved = 0x%x, id = 0x%x}, "<br>
+                    "option = %#x, send_size = 0, rcv_size = %llu, "<br>
+                    "rcv_name = %#x, timeout = %u, notify = %#x)",<br>
+                        exc_msg.hdr.msgh_bits,<br>
+                        exc_msg.hdr.msgh_size,<br>
+                        exc_msg.hdr.msgh_remote_port,<br>
+                        exc_msg.hdr.msgh_local_port,<br>
+                        exc_msg.hdr.msgh_reserved,<br>
+                        exc_msg.hdr.msgh_id,<br>
+                        options,<br>
+                        (uint64_t)sizeof (exc_msg.data),<br>
+                        port,<br>
+                        mach_msg_timeout,<br>
+                        notify_port);<br>
+    }<br>
+<br>
+    mach_msg_return_t mach_err =<br>
+        ::mach_msg (&exc_msg.hdr,<br>
+                    options,                  // options<br>
+                    0,                        // Send size<br>
+                    sizeof (exc_msg.data),    // Receive size<br>
+                    port,                     // exception port to watch for<br>
+                                              // exception on<br>
+                    mach_msg_timeout,         // timeout in msec (obeyed only<br>
+                                              // if MACH_RCV_TIMEOUT is ORed<br>
+                                              // into the options parameter)<br>
+                    notify_port);<br>
+    error.SetError(mach_err, eErrorTypeMachKernel);<br>
+<br>
+    // Dump any errors we get<br>
+    if (error.Fail() && log)<br>
+    {<br>
+        log->Printf("::mach_msg(msg->{<wbr>bits = %#x, size = %u remote_port = %#x, "<br>
+                    "local_port = %#x, reserved = 0x%x, id = 0x%x}, "<br>
+                    "option = %#x, send_size = %u, rcv_size = %lu, rcv_name "<br>
+                    "= %#x, timeout = %u, notify = %#x) failed: %s",<br>
+                    exc_msg.hdr.msgh_bits,<br>
+                    exc_msg.hdr.msgh_size,<br>
+                    exc_msg.hdr.msgh_remote_port,<br>
+                    exc_msg.hdr.msgh_local_port,<br>
+                    exc_msg.hdr.msgh_reserved,<br>
+                    exc_msg.hdr.msgh_id,<br>
+                    options,<br>
+                    0,<br>
+                    sizeof(exc_msg.data),<br>
+                    port,<br>
+                    mach_msg_timeout,<br>
+                    notify_port,<br>
+                    error.AsCString());<br>
+    }<br>
+    return error;<br>
+}<br>
+<br>
+void<br>
+MachException::Message::Dump(<wbr>Stream &stream) const<br>
+{<br>
+    stream.Printf("  exc_msg { bits = 0x%8.8x size = 0x%8.8x remote-port = "<br>
+                  "0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x id = "<br>
+                  "0x%8.8x }\n",<br>
+                  exc_msg.hdr.msgh_bits,<br>
+                  exc_msg.hdr.msgh_size,<br>
+                  exc_msg.hdr.msgh_remote_port,<br>
+                  exc_msg.hdr.msgh_local_port,<br>
+                  exc_msg.hdr.msgh_reserved,<br>
+                  exc_msg.hdr.msgh_id);<br>
+<br>
+    stream.Printf("  reply_msg { bits = 0x%8.8x size = 0x%8.8x remote-port = "<br>
+                  "0x%8.8x local-port = 0x%8.8x reserved = 0x%8.8x id = "<br>
+                  "0x%8.8x }",<br>
+                  reply_msg.hdr.msgh_bits,<br>
+                  reply_msg.hdr.msgh_size,<br>
+                  reply_msg.hdr.msgh_remote_<wbr>port,<br>
+                  reply_msg.hdr.msgh_local_port,<br>
+                  reply_msg.hdr.msgh_reserved,<br>
+                  reply_msg.hdr.msgh_id);<br>
+}<br>
+<br>
+bool<br>
+MachException::Message::<wbr>CatchExceptionRaise(task_t task)<br>
+{<br>
+    bool success = false;<br>
+    // locker will keep a mutex locked until it goes out of scope<br>
+//    PThreadMutex::Locker locker(&g_message_mutex);<br>
+    //    DNBLogThreaded("calling  mach_exc_server");<br>
+    state.task_port = task;<br>
+    g_message = &state;<br>
+    // The exc_server function is the MIG generated server handling function<br>
+    // to handle messages from the kernel relating to the occurrence of an<br>
+    // exception in a thread. Such messages are delivered to the exception port<br>
+    // set via thread_set_exception_ports or task_set_exception_ports. When an<br>
+    // exception occurs in a thread, the thread sends an exception message to<br>
+    // its exception port, blocking in the kernel waiting for the receipt of a<br>
+    // reply. The exc_server function performs all necessary argument handling<br>
+    // for this kernel message and calls catch_exception_raise,<br>
+    // catch_exception_raise_state or catch_exception_raise_state_<wbr>identity,<br>
+    // which should handle the exception. If the called routine returns<br>
+    // KERN_SUCCESS, a reply message will be sent, allowing the thread to<br>
+    // continue from the point of the exception; otherwise, no reply message<br>
+    // is sent and the called routine must have dealt with the exception<br>
+    // thread directly.<br>
+    if (mach_exc_server (&exc_msg.hdr, &reply_msg.hdr))<br>
+    {<br>
+        success = true;<br>
+    }<br>
+    else<br>
+    {<br>
+        Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                          LIBLLDB_LOG_VERBOSE));<br>
+        if (log)<br>
+            log->Printf("MachException::<wbr>Message::%s(): mach_exc_server "<br>
+                        "returned zero...", __FUNCTION__);<br>
+    }<br>
+    g_message = NULL;<br>
+    return success;<br>
+}<br>
+<br>
+Error<br>
+MachException::Message::<wbr>Reply(::pid_t inferior_pid, task_t inferior_task,<br>
+                              int signal)<br>
+{<br>
+    // Reply to the exception...<br>
+    Error error;<br>
+<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+<br>
+    // If we had a soft signal, we need to update the thread first so it can<br>
+    // continue without signaling<br>
+    int soft_signal = state.SoftSignal();<br>
+    if (soft_signal)<br>
+    {<br>
+        int state_pid = -1;<br>
+        if (inferior_task == state.task_port)<br>
+        {<br>
+            // This is our task, so we can update the signal to send to it<br>
+            state_pid = inferior_pid;<br>
+            soft_signal = signal;<br>
+        }<br>
+        else<br>
+        {<br>
+            auto mach_err = ::pid_for_task(state.task_<wbr>port, &state_pid);<br>
+            if (mach_err)<br>
+            {<br>
+                error.SetError(mach_err, eErrorTypeMachKernel);<br>
+                if (log)<br>
+                    log->Printf("MachException::<wbr>Message::%s(): pid_for_task() "<br>
+                                "failed: %s", __FUNCTION__, error.AsCString());<br>
+                return error;<br>
+            }<br>
+        }<br>
+<br>
+        lldbassert(state_pid != -1);<br>
+        if (state_pid != -1)<br>
+        {<br>
+            errno = 0;<br>
+            caddr_t thread_port_caddr = (caddr_t)(uintptr_t)state.<wbr>thread_port;<br>
+            if (::ptrace(PT_THUPDATE, state_pid, thread_port_caddr, soft_signal)<br>
+                != 0)<br>
+                error.SetError(errno, eErrorTypePOSIX);<br>
+<br>
+            if (!error.Success())<br>
+            {<br>
+                if (log)<br>
+                    log->Printf("::ptrace(request = PT_THUPDATE, pid = "<br>
+                                "0x%4.4x, tid = 0x%4.4x, signal = %i)",<br>
+                                state_pid, state.thread_port, soft_signal);<br>
+                return error;<br>
+            }<br>
+        }<br>
+    }<br>
+<br>
+    if (log)<br>
+        log->Printf("::mach_msg ( msg->{bits = %#x, size = %u, remote_port "<br>
+                    "= %#x, local_port = %#x, reserved = 0x%x, id = 0x%x}, "<br>
+                    "option = %#x, send_size = %u, rcv_size = %u, rcv_name "<br>
+                    "= %#x, timeout = %u, notify = %#x)",<br>
+                    reply_msg.hdr.msgh_bits,<br>
+                    reply_msg.hdr.msgh_size,<br>
+                    reply_msg.hdr.msgh_remote_<wbr>port,<br>
+                    reply_msg.hdr.msgh_local_port,<br>
+                    reply_msg.hdr.msgh_reserved,<br>
+                    reply_msg.hdr.msgh_id,<br>
+                    MACH_SEND_MSG | MACH_SEND_INTERRUPT,<br>
+                    reply_msg.hdr.msgh_size,<br>
+                    0,<br>
+                    MACH_PORT_NULL,<br>
+                    MACH_MSG_TIMEOUT_NONE,<br>
+                    MACH_PORT_NULL);<br>
+<br>
+    auto mach_err = ::mach_msg(&reply_msg.hdr,<br>
+                               MACH_SEND_MSG | MACH_SEND_INTERRUPT,<br>
+                               reply_msg.hdr.msgh_size,<br>
+                               0,<br>
+                               MACH_PORT_NULL,<br>
+                               MACH_MSG_TIMEOUT_NONE,<br>
+                               MACH_PORT_NULL);<br>
+    if (mach_err)<br>
+        error.SetError(mach_err, eErrorTypeMachKernel);<br>
+<br>
+    // Log our error if we have one.<br>
+    if (error.Fail() && log)<br>
+    {<br>
+        if (error.GetError() == MACH_SEND_INTERRUPTED)<br>
+        {<br>
+            log->PutCString("::mach_msg() - send interrupted");<br>
+            // TODO: keep retrying to reply???<br>
+        }<br>
+        else if (state.task_port == inferior_task)<br>
+        {<br>
+            log->Printf("mach_msg(): returned an error when replying "<br>
+                        "to a mach exception: error = %u (%s)",<br>
+                        error.GetError(), error.AsCString());<br>
+        }<br>
+        else<br>
+        {<br>
+            log->Printf("::mach_msg() - failed (child of task): %u (%s)",<br>
+                        error.GetError(), error.AsCString());<br>
+        }<br>
+    }<br>
+<br>
+    return error;<br>
+}<br>
+<br>
+#define PREV_EXC_MASK_ALL (EXC_MASK_BAD_ACCESS      | \<br>
+                           EXC_MASK_BAD_INSTRUCTION | \<br>
+                           EXC_MASK_ARITHMETIC      | \<br>
+                           EXC_MASK_EMULATION       | \<br>
+                           EXC_MASK_SOFTWARE        | \<br>
+                           EXC_MASK_BREAKPOINT      | \<br>
+                           EXC_MASK_SYSCALL         | \<br>
+                           EXC_MASK_MACH_SYSCALL    | \<br>
+                           EXC_MASK_RPC_ALERT       | \<br>
+                           EXC_MASK_MACHINE)<br>
+<br>
+// Don't listen for EXC_RESOURCE, it should really get handled by the system handler.<br>
+<br>
+#ifndef EXC_RESOURCE<br>
+#define EXC_RESOURCE 11<br>
+#endif<br>
+<br>
+#ifndef EXC_MASK_RESOURCE<br>
+#define EXC_MASK_RESOURCE (1 << EXC_RESOURCE)<br>
+#endif<br>
+<br>
+#define LLDB_EXC_MASK (EXC_MASK_ALL & ~EXC_MASK_RESOURCE)<br>
+<br>
+Error<br>
+MachException::PortInfo::<wbr>Save(task_t task)<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+<br>
+    if (log)<br>
+        log->Printf("MachException::<wbr>PortInfo::%s(task = 0x%4.4x)",<br>
+                    __FUNCTION__, task);<br>
+<br>
+    // Be careful to be able to have debugserver built on a newer OS than what<br>
+    // it is currently running on by being able to start with all exceptions<br>
+    // and back off to just what is supported on the current system<br>
+    mask = LLDB_EXC_MASK;<br>
+<br>
+    count = (sizeof(ports) / sizeof(ports[0]));<br>
+    auto mach_err = ::task_get_exception_ports(<wbr>task, mask, masks, &count, ports,<br>
+                                               behaviors, flavors);<br>
+    if (mach_err)<br>
+        error.SetError(mach_err, eErrorTypeMachKernel);<br>
+<br>
+    if (log)<br>
+    {<br>
+        if (error.Success())<br>
+        {<br>
+            log->Printf("::task_get_<wbr>exception_ports(task = 0x%4.4x, mask = "<br>
+                        "0x%x, maskCnt => %u, ports, behaviors, flavors)",<br>
+                        task, mask, count);<br>
+        }<br>
+        else<br>
+        {<br>
+            log->Printf("::task_get_<wbr>exception_ports(task = 0x%4.4x, mask = 0x%x, "<br>
+                        "maskCnt => %u, ports, behaviors, flavors) error: %u (%s)",<br>
+                        task, mask, count, error.GetError(), error.AsCString());<br>
+        }<br>
+    }<br>
+<br>
+    if ((error.GetError() == KERN_INVALID_ARGUMENT) &&<br>
+        (mask != PREV_EXC_MASK_ALL))<br>
+    {<br>
+        mask = PREV_EXC_MASK_ALL;<br>
+        count = (sizeof(ports) / sizeof(ports[0]));<br>
+        mach_err = ::task_get_exception_ports(<wbr>task, mask, masks, &count, ports,<br>
+                                              behaviors, flavors);<br>
+        error.SetError(mach_err, eErrorTypeMachKernel);<br>
+        if (log)<br>
+        {<br>
+            if (error.Success())<br>
+            {<br>
+                log->Printf("::task_get_<wbr>exception_ports(task = 0x%4.4x, "<br>
+                            "mask = 0x%x, maskCnt => %u, ports, behaviors, "<br>
+                            "flavors)", task, mask, count);<br>
+            }<br>
+            else<br>
+            {<br>
+                log->Printf("::task_get_<wbr>exception_ports(task = 0x%4.4x, mask = "<br>
+                            "0x%x, maskCnt => %u, ports, behaviors, flavors) "<br>
+                            "error: %u (%s)", task, mask, count,<br>
+                            error.GetError(), error.AsCString());<br>
+            }<br>
+        }<br>
+    }<br>
+    if (error.Fail())<br>
+    {<br>
+        mask = 0;<br>
+        count = 0;<br>
+    }<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+MachException::PortInfo::<wbr>Restore(task_t task)<br>
+{<br>
+    Error error;<br>
+<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+<br>
+    if (log)<br>
+        log->Printf("MachException::<wbr>PortInfo::Restore(task = 0x%4.4x)", task);<br>
+<br>
+    uint32_t i = 0;<br>
+    if (count > 0)<br>
+    {<br>
+        for (i = 0; i < count; i++)<br>
+        {<br>
+            auto mach_err = ::task_set_exception_ports(<wbr>task, masks[i], ports[i],<br>
+                                                       behaviors[i],<br>
+                                                       flavors[i]);<br>
+            if (mach_err)<br>
+                error.SetError(mach_err, eErrorTypeMachKernel);<br>
+            if (log)<br>
+            {<br>
+                if (error.Success())<br>
+                {<br>
+                    log->Printf("::task_set_<wbr>exception_ports(task = 0x%4.4x, "<br>
+                                "exception_mask = 0x%8.8x, new_port = 0x%4.4x, "<br>
+                                "behavior = 0x%8.8x, new_flavor = 0x%8.8x)",<br>
+                                task, masks[i], ports[i], behaviors[i],<br>
+                                flavors[i]);<br>
+                }<br>
+                else<br>
+                {<br>
+                    log->Printf("::task_set_<wbr>exception_ports(task = 0x%4.4x, "<br>
+                                "exception_mask = 0x%8.8x, new_port = 0x%4.4x, "<br>
+                                "behavior = 0x%8.8x, new_flavor = 0x%8.8x): "<br>
+                                "error %u (%s)", task, masks[i], ports[i],<br>
+                                behaviors[i], flavors[i], error.GetError(),<br>
+                                error.AsCString());<br>
+                }<br>
+            }<br>
+<br>
+            // Bail if we encounter any errors<br>
+            if (error.Fail())<br>
+                break;<br>
+        }<br>
+    }<br>
+<br>
+    count = 0;<br>
+    return error;<br>
+}<br>
+<br>
+const char *<br>
+MachException::Name(<wbr>exception_type_t exc_type)<br>
+{<br>
+    switch (exc_type)<br>
+    {<br>
+    case EXC_BAD_ACCESS:        return "EXC_BAD_ACCESS";<br>
+    case EXC_BAD_INSTRUCTION:   return "EXC_BAD_INSTRUCTION";<br>
+    case EXC_ARITHMETIC:        return "EXC_ARITHMETIC";<br>
+    case EXC_EMULATION:         return "EXC_EMULATION";<br>
+    case EXC_SOFTWARE:          return "EXC_SOFTWARE";<br>
+    case EXC_BREAKPOINT:        return "EXC_BREAKPOINT";<br>
+    case EXC_SYSCALL:           return "EXC_SYSCALL";<br>
+    case EXC_MACH_SYSCALL:      return "EXC_MACH_SYSCALL";<br>
+    case EXC_RPC_ALERT:         return "EXC_RPC_ALERT";<br>
+#ifdef EXC_CRASH<br>
+    case EXC_CRASH:             return "EXC_CRASH";<br>
+#endif<br>
+    default:<br>
+        break;<br>
+    }<br>
+    return NULL;<br>
+}<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/MachException.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/MachException.h?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>MachException.h?rev=280604&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/MachException.h (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/MachException.h Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,163 @@<br>
+//===-- MachException.h ------------------------------<wbr>-----------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//  Created by Greg Clayton on 6/18/07.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+<br>
+#ifndef __MachException_h__<br>
+#define __MachException_h__<br>
+<br>
+#include <mach/mach.h><br>
+#include <vector><br>
+<br>
+#include "lldb/lldb-private-forward.h"<br>
+#include "lldb/lldb-types.h"<br>
+#include "lldb/Host/Debug.h"<br>
+<br>
+namespace lldb_private<br>
+{<br>
+namespace process_darwin<br>
+{<br>
+<br>
+typedef union MachMessageTag<br>
+{<br>
+    mach_msg_header_t hdr;<br>
+    char data[1024];<br>
+} MachMessage;<br>
+<br>
+<br>
+class MachException<br>
+{<br>
+public:<br>
+<br>
+    struct PortInfo<br>
+    {<br>
+        exception_mask_t        mask; // the exception mask for this device which may be a subset of EXC_MASK_ALL...<br>
+        exception_mask_t        masks[EXC_TYPES_COUNT];<br>
+        mach_port_t             ports[EXC_TYPES_COUNT];<br>
+        exception_behavior_t    behaviors[EXC_TYPES_COUNT];<br>
+        thread_state_flavor_t   flavors[EXC_TYPES_COUNT];<br>
+        mach_msg_type_number_t  count;<br>
+<br>
+        Error<br>
+        Save(task_t task);<br>
+<br>
+        Error<br>
+        Restore(task_t task);<br>
+    };<br>
+<br>
+    struct Data<br>
+    {<br>
+        task_t task_port;<br>
+        thread_t thread_port;<br>
+        exception_type_t exc_type;<br>
+        std::vector<mach_exception_<wbr>data_type_t> exc_data;<br>
+        Data() :<br>
+            task_port(TASK_NULL),<br>
+            thread_port(THREAD_NULL),<br>
+            exc_type(0),<br>
+            exc_data()<br>
+            {<br>
+            }<br>
+<br>
+        void<br>
+        Clear()<br>
+        {<br>
+            task_port = TASK_NULL;<br>
+            thread_port = THREAD_NULL;<br>
+            exc_type = 0;<br>
+            exc_data.clear();<br>
+        }<br>
+<br>
+        bool<br>
+        IsValid() const<br>
+        {<br>
+            return  task_port != TASK_NULL &&<br>
+                    thread_port != THREAD_NULL &&<br>
+                    exc_type != 0;<br>
+        }<br>
+<br>
+        // Return the SoftSignal for this MachException data, or zero if there is none<br>
+        int<br>
+        SoftSignal() const<br>
+        {<br>
+            if (exc_type == EXC_SOFTWARE && exc_data.size() == 2 && exc_data[0] == EXC_SOFT_SIGNAL)<br>
+                return static_cast<int>(exc_data[1]);<br>
+            return 0;<br>
+        }<br>
+<br>
+        bool<br>
+        IsBreakpoint() const<br>
+        {<br>
+            return (exc_type == EXC_BREAKPOINT || ((exc_type == EXC_SOFTWARE) && exc_data[0] == 1));<br>
+        }<br>
+<br>
+        bool<br>
+        GetStopInfo(ThreadStopInfo *stop_info, const UnixSignals &signals,<br>
+                         Stream &stream) const;<br>
+    };<br>
+<br>
+    struct Message<br>
+    {<br>
+        MachMessage exc_msg;<br>
+        MachMessage reply_msg;<br>
+        Data state;<br>
+<br>
+        Message() :<br>
+            state()<br>
+        {<br>
+            memset(&exc_msg,   0, sizeof(exc_msg));<br>
+            memset(&reply_msg, 0, sizeof(reply_msg));<br>
+        }<br>
+<br>
+        bool<br>
+        CatchExceptionRaise(task_t task);<br>
+<br>
+        Error<br>
+        Reply(::pid_t inferior_pid, task_t inferior_task, int signal);<br>
+<br>
+        Error<br>
+        Receive(mach_port_t receive_port,<br>
+                mach_msg_option_t options,<br>
+                mach_msg_timeout_t timeout,<br>
+                mach_port_t notify_port = MACH_PORT_NULL);<br>
+<br>
+        void<br>
+        Dump(Stream &stream) const;<br>
+<br>
+        typedef std::vector<Message>        collection;<br>
+        typedef collection::iterator        iterator;<br>
+        typedef collection::const_iterator    const_iterator;<br>
+    };<br>
+<br>
+    enum<br>
+    {<br>
+        e_actionForward,    // Forward signal to inferior process<br>
+        e_actionStop,        // Stop when this signal is received<br>
+    };<br>
+    struct Action<br>
+    {<br>
+        task_t task_port;            // Set to TASK_NULL for any TASK<br>
+        thread_t thread_port;        // Set to THREAD_NULL for any thread<br>
+        exception_type_t exc_mask;    // Mach exception mask to watch for<br>
+        std::vector<mach_exception_<wbr>data_type_t> exc_data_mask;    // Mask to apply to exception data, or empty to ignore exc_data value for exception<br>
+        std::vector<mach_exception_<wbr>data_type_t> exc_data_value;    // Value to compare to exception data after masking, or empty to ignore exc_data value for exception<br>
+        uint8_t flags;                // Action flags describing what to do with the exception<br>
+    };<br>
+<br>
+    static const char*<br>
+    Name(exception_type_t exc_type);<br>
+};<br>
+<br>
+} // namespace process_darwin<br>
+} // namespace lldb_private<br>
+<br>
+#endif<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeProcessDarwin.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>NativeProcessDarwin.cpp?rev=<wbr>280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeProcessDarwin.cpp (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeProcessDarwin.cpp Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,1825 @@<br>
+//===-- NativeProcessDarwin.cpp ------------------------------<wbr>---*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "NativeProcessDarwin.h"<br>
+<br>
+// C includes<br>
+#include <mach/mach_init.h><br>
+#include <mach/mach_traps.h><br>
+#include <sys/ptrace.h><br>
+#include <sys/stat.h><br>
+#include <sys/sysctl.h><br>
+#include <sys/types.h><br>
+<br>
+// C++ includes<br>
+// LLDB includes<br>
+#include "lldb/Core/Log.h"<br>
+#include "lldb/Core/State.h"<br>
+#include "lldb/Core/StreamString.h"<br>
+#include "lldb/Target/<wbr>ProcessLaunchInfo.h"<br>
+#include "lldb/Utility/PseudoTerminal.<wbr>h"<br>
+<br>
+#include "CFBundle.h"<br>
+#include "CFString.h"<br>
+#include "DarwinProcessLauncher.h"<br>
+<br>
+#include "MachException.h"<br>
+<br>
+using namespace lldb;<br>
+using namespace lldb_private;<br>
+using namespace lldb_private::process_darwin;<br>
+using namespace lldb_private::darwin_process_<wbr>launcher;<br>
+<br>
+// ------------------------------<wbr>------------------------------<wbr>-----------------<br>
+// Hidden Impl<br>
+// ------------------------------<wbr>------------------------------<wbr>-----------------<br>
+<br>
+namespace<br>
+{<br>
+    struct hack_task_dyld_info {<br>
+        mach_vm_address_t   all_image_info_addr;<br>
+        mach_vm_size_t      all_image_info_size;<br>
+    };<br>
+}<br>
+<br>
+// ------------------------------<wbr>------------------------------<wbr>-----------------<br>
+// Public Static Methods<br>
+// ------------------------------<wbr>------------------------------<wbr>-----------------<br>
+<br>
+Error<br>
+NativeProcessProtocol::<wbr>Launch(ProcessLaunchInfo &launch_info,<br>
+                              NativeProcessProtocol::<wbr>NativeDelegate<br>
+                              &native_delegate,<br>
+                              MainLoop &mainloop,<br>
+                              NativeProcessProtocolSP &native_process_sp)<br>
+{<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    Error error;<br>
+<br>
+    // Verify the working directory is valid if one was specified.<br>
+    FileSpec working_dir(launch_info.<wbr>GetWorkingDirectory());<br>
+    if (working_dir &&<br>
+        (!working_dir.ResolvePath() ||<br>
+         working_dir.GetFileType() != FileSpec::eFileTypeDirectory))<br>
+    {<br>
+        error.<wbr>SetErrorStringWithFormat("No such file or directory: %s",<br>
+                                       working_dir.GetCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    // Launch the inferior.<br>
+    int pty_master_fd = -1;<br>
+    LaunchFlavor launch_flavor = LaunchFlavor::Default;<br>
+<br>
+    error = LaunchInferior(launch_info, &pty_master_fd, &launch_flavor);<br>
+<br>
+    // Handle launch failure.<br>
+    if (!error.Success())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s() failed to launch process: "<br>
+                        "%s",<br>
+                        __FUNCTION__, error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    // Handle failure to return a pid.<br>
+    if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID)<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s() launch succeeded but no "<br>
+                        "pid was returned!  Aborting.", __FUNCTION__);<br>
+        return error;<br>
+    }<br>
+<br>
+    // Create the Darwin native process impl.<br>
+    std::shared_ptr<<wbr>NativeProcessDarwin><br>
+        np_darwin_sp(new NativeProcessDarwin(launch_<wbr>info.GetProcessID(),<br>
+                                             pty_master_fd));<br>
+    if (!np_darwin_sp-><wbr>RegisterNativeDelegate(native_<wbr>delegate))<br>
+    {<br>
+        native_process_sp.reset ();<br>
+        error.SetErrorStringWithFormat ("failed to register the native delegate");<br>
+        return error;<br>
+    }<br>
+<br>
+    // Finalize the processing needed to debug the launched process with<br>
+    // a NativeProcessDarwin instance.<br>
+    error = np_darwin_sp->FinalizeLaunch(<wbr>launch_flavor, mainloop);<br>
+    if (!error.Success())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s() aborting, failed to finalize"<br>
+                        " the launching of the process: %s",<br>
+                        __FUNCTION__, error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    // Return the process and process id to the caller through the launch args.<br>
+    native_process_sp = np_darwin_sp;<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessProtocol::<wbr>Attach(lldb::pid_t pid,<br>
+                              NativeProcessProtocol::<wbr>NativeDelegate<br>
+                              &native_delegate,<br>
+                              MainLoop &mainloop,<br>
+                              NativeProcessProtocolSP &native_process_sp)<br>
+{<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+    if (log)<br>
+        log->Printf ("NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__,<br>
+                     pid);<br>
+<br>
+    // Retrieve the architecture for the running process.<br>
+    ArchSpec process_arch;<br>
+    Error error = ResolveProcessArchitecture(<wbr>pid, process_arch);<br>
+    if (!error.Success())<br>
+        return error;<br>
+<br>
+    // TODO get attach to return this value.<br>
+    const int pty_master_fd = -1;<br>
+    std::shared_ptr<<wbr>NativeProcessDarwin> native_process_darwin_sp(<br>
+                                   new NativeProcessDarwin(pid, pty_master_fd));<br>
+<br>
+    if (!native_process_darwin_sp-><wbr>RegisterNativeDelegate(native_<wbr>delegate))<br>
+    {<br>
+        error.<wbr>SetErrorStringWithFormat("<wbr>failed to register the native "<br>
+                                       "delegate");<br>
+        return error;<br>
+    }<br>
+<br>
+    native_process_darwin_sp-><wbr>AttachToInferior(mainloop, pid, error);<br>
+    if (!error.Success())<br>
+        return error;<br>
+<br>
+    native_process_sp = native_process_darwin_sp;<br>
+    return error;<br>
+}<br>
+<br>
+// ------------------------------<wbr>------------------------------<wbr>-----------------<br>
+// ctor/dtor<br>
+// ------------------------------<wbr>------------------------------<wbr>-----------------<br>
+<br>
+NativeProcessDarwin::<wbr>NativeProcessDarwin(lldb::pid_<wbr>t pid, int pty_master_fd) :<br>
+    NativeProcessProtocol(pid),<br>
+    m_task(TASK_NULL),<br>
+    m_did_exec(false),<br>
+    m_cpu_type(0),<br>
+    m_exception_port(MACH_PORT_<wbr>NULL),<br>
+    m_exc_port_info(),<br>
+    m_exception_thread(nullptr),<br>
+    m_exception_messages_mutex(),<br>
+    m_sent_interrupt_signo(0),<br>
+    m_auto_resume_signo(0),<br>
+    m_thread_list(),<br>
+    m_thread_actions(),<br>
+    m_waitpid_pipe(),<br>
+    m_waitpid_thread(nullptr),<br>
+    m_waitpid_reader_handle()<br>
+{<br>
+    // TODO add this to the NativeProcessProtocol constructor.<br>
+    m_terminal_fd = pty_master_fd;<br>
+}<br>
+<br>
+NativeProcessDarwin::~<wbr>NativeProcessDarwin()<br>
+{<br>
+}<br>
+<br>
+// ------------------------------<wbr>------------------------------<wbr>-----------------<br>
+// Instance methods<br>
+// ------------------------------<wbr>------------------------------<wbr>-----------------<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>FinalizeLaunch(LaunchFlavor launch_flavor,<br>
+                                    MainLoop &main_loop)<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+#if 0<br>
+    m_path = path;<br>
+    size_t i;<br>
+    char const *arg;<br>
+    for (i=0; (arg = argv[i]) != NULL; i++)<br>
+        m_args.push_back(arg);<br>
+#endif<br>
+<br>
+    error = StartExceptionThread();<br>
+    if (!error.Success())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): failure starting the "<br>
+                        "mach exception port monitor thread: %s",<br>
+                        __FUNCTION__, error.AsCString());<br>
+<br>
+        // Terminate the inferior process.  There's nothing meaningful we can<br>
+        // do if we can't receive signals and exceptions.  Since we launched<br>
+        // the process, it's fair game for us to kill it.<br>
+        ::ptrace(PT_KILL, m_pid, 0, 0);<br>
+        SetState(eStateExited);<br>
+<br>
+        return error;<br>
+    }<br>
+<br>
+    StartSTDIOThread();<br>
+<br>
+    if (launch_flavor == LaunchFlavor::PosixSpawn)<br>
+    {<br>
+        SetState(eStateAttaching);<br>
+        errno = 0;<br>
+        int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0);<br>
+        if (err == 0)<br>
+        {<br>
+            // m_flags |= eMachProcessFlagsAttached;<br>
+            if (log)<br>
+                log->Printf("<wbr>NativeProcessDarwin::%s(): successfully spawned "<br>
+                            "process with pid %" PRIu64, __FUNCTION__, m_pid);<br>
+        }<br>
+        else<br>
+        {<br>
+            error.SetErrorToErrno();<br>
+            SetState(eStateExited);<br>
+            if (log)<br>
+                log->Printf("<wbr>NativeProcessDarwin::%s(): error: failed to "<br>
+                            "attach to spawned pid %" PRIu64 " (error=%d (%s))",<br>
+                            __FUNCTION__, m_pid, (int)error.GetError(),<br>
+                            error.AsCString());<br>
+            return error;<br>
+        }<br>
+    }<br>
+<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeProcessDarwin::%s(): new pid is %" PRIu64 "...",<br>
+                    __FUNCTION__, m_pid);<br>
+<br>
+    // Spawn a thread to reap our child inferior process...<br>
+    error = StartWaitpidThread(main_loop);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): failed to start waitpid() "<br>
+                        "thread: %s", __FUNCTION__, error.AsCString());<br>
+        kill(SIGKILL, static_cast<::pid_t>(m_pid));<br>
+        return error;<br>
+    }<br>
+<br>
+    if (TaskPortForProcessID(error) == TASK_NULL)<br>
+    {<br>
+        // We failed to get the task for our process ID which is bad.<br>
+        // Kill our process; otherwise, it will be stopped at the entry<br>
+        // point and get reparented to someone else and never go away.<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): could not get task port "<br>
+                        "for process, sending SIGKILL and exiting: %s",<br>
+                        __FUNCTION__, error.AsCString());<br>
+        kill(SIGKILL, static_cast<::pid_t>(m_pid));<br>
+        return error;<br>
+    }<br>
+<br>
+    // Indicate that we're stopped, as we always launch suspended.<br>
+    SetState(eStateStopped);<br>
+<br>
+    // Success.<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>SaveExceptionPortInfo()<br>
+{<br>
+    return m_exc_port_info.Save(m_task);<br>
+}<br>
+<br>
+bool<br>
+NativeProcessDarwin::<wbr>ProcessUsingSpringBoard() const<br>
+{<br>
+    // TODO implement flags<br>
+    // return (m_flags & eMachProcessFlagsUsingSBS) != 0;<br>
+    return false;<br>
+}<br>
+<br>
+bool<br>
+NativeProcessDarwin::<wbr>ProcessUsingBackBoard() const<br>
+{<br>
+    // TODO implement flags<br>
+    // return (m_flags & eMachProcessFlagsUsingBKS) != 0;<br>
+    return false;<br>
+}<br>
+<br>
+// Called by the exception thread when an exception has been received from<br>
+// our process. The exception message is completely filled and the exception<br>
+// data has already been copied.<br>
+void<br>
+NativeProcessDarwin::<wbr>ExceptionMessageReceived(const MachException::Message&<br>
+                                              message)<br>
+{<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_exception_messages_<wbr>mutex);<br>
+    if (m_exception_messages.empty())<br>
+    {<br>
+        // Suspend the task the moment we receive our first exception message.<br>
+        SuspendTask();<br>
+    }<br>
+<br>
+    // Use a locker to automatically unlock our mutex in case of exceptions<br>
+    // Add the exception to our internal exception stack<br>
+    m_exception_messages.push_<wbr>back(message);<br>
+<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeProcessDarwin::%s(): new queued message count: %lu",<br>
+                    __FUNCTION__, m_exception_messages.size());<br>
+}<br>
+<br>
+void*<br>
+NativeProcessDarwin::<wbr>ExceptionThread(void *arg)<br>
+{<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+    if (!arg)<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): cannot run mach exception "<br>
+                        "thread, mandatory process arg was null", __FUNCTION__);<br>
+        return nullptr;<br>
+    }<br>
+<br>
+    return reinterpret_cast<<wbr>NativeProcessDarwin*>(arg)-><wbr>DoExceptionThread();<br>
+}<br>
+<br>
+void*<br>
+NativeProcessDarwin::<wbr>DoExceptionThread()<br>
+{<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeProcessDarwin::%s(arg=%<wbr>p) starting thread...",<br>
+                    __FUNCTION__, this);<br>
+<br>
+    pthread_setname_np("exception monitoring thread");<br>
+<br>
+    // Ensure we don't get CPU starved.<br>
+    MaybeRaiseThreadPriority();<br>
+<br>
+    // We keep a count of the number of consecutive exceptions received so<br>
+    // we know to grab all exceptions without a timeout. We do this to get a<br>
+    // bunch of related exceptions on our exception port so we can process<br>
+    // then together. When we have multiple threads, we can get an exception<br>
+    // per thread and they will come in consecutively. The main loop in this<br>
+    // thread can stop periodically if needed to service things related to this<br>
+    // process.<br>
+    //<br>
+    // [did we lose some words here?]<br>
+    //<br>
+    // flag set in the options, so we will wait forever for an exception on<br>
+    //0 our exception port. After we get one exception, we then will use the<br>
+    // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current<br>
+    // exceptions for our process. After we have received the last pending<br>
+    // exception, we will get a timeout which enables us to then notify<br>
+    // our main thread that we have an exception bundle available. We then wait<br>
+    // for the main thread to tell this exception thread to start trying to get<br>
+    // exceptions messages again and we start again with a mach_msg read with<br>
+    // infinite timeout.<br>
+    //<br>
+    // We choose to park a thread on this, rather than polling, because the<br>
+    // polling is expensive.  On devices, we need to minimize overhead caused<br>
+    // by the process monitor.<br>
+    uint32_t num_exceptions_received = 0;<br>
+    Error error;<br>
+    task_t task = m_task;<br>
+    mach_msg_timeout_t periodic_timeout = 0;<br>
+<br>
+#if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)<br>
+    mach_msg_timeout_t watchdog_elapsed = 0;<br>
+    mach_msg_timeout_t watchdog_timeout = 60 * 1000;<br>
+    ::pid_t pid = (::pid_t)process->GetID();<br>
+    CFReleaser<<wbr>SBSWatchdogAssertionRef> watchdog;<br>
+<br>
+    if (process-><wbr>ProcessUsingSpringBoard())<br>
+    {<br>
+        // Request a renewal for every 60 seconds if we attached using<br>
+        // SpringBoard.<br>
+        watchdog.reset(::<wbr>SBSWatchdogAssertionCreateForP<wbr>ID(nullptr, pid, 60));<br>
+        if (log)<br>
+            log->Printf("::<wbr>SBSWatchdogAssertionCreateForP<wbr>ID(NULL, %4.4x, 60) "<br>
+                        "=> %p", pid, watchdog.get());<br>
+<br>
+        if (watchdog.get())<br>
+        {<br>
+            ::SBSWatchdogAssertionRenew (watchdog.get());<br>
+<br>
+            CFTimeInterval watchdogRenewalInterval =<br>
+                ::<wbr>SBSWatchdogAssertionGetRenewal<wbr>Interval (watchdog.get());<br>
+            if (log)<br>
+                log->Printf("::<wbr>SBSWatchdogAssertionGetRenewal<wbr>Interval(%p) => "<br>
+                            "%g seconds", watchdog.get(),<br>
+                            watchdogRenewalInterval);<br>
+            if (watchdogRenewalInterval > 0.0)<br>
+            {<br>
+                watchdog_timeout =<br>
+                    (mach_msg_timeout_t)<wbr>watchdogRenewalInterval * 1000;<br>
+                if (watchdog_timeout > 3000)<br>
+                {<br>
+                    // Give us a second to renew our timeout.<br>
+                    watchdog_timeout -= 1000;<br>
+                }<br>
+                else if (watchdog_timeout > 1000)<br>
+                {<br>
+                    // Give us a quarter of a second to renew our timeout.<br>
+                    watchdog_timeout -= 250;<br>
+                }<br>
+            }<br>
+        }<br>
+        if (periodic_timeout == 0 || periodic_timeout > watchdog_timeout)<br>
+            periodic_timeout = watchdog_timeout;<br>
+    }<br>
+#endif  // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)<br>
+<br>
+#ifdef WITH_BKS<br>
+    CFReleaser<<wbr>BKSWatchdogAssertionRef> watchdog;<br>
+    if (process-><wbr>ProcessUsingBackBoard())<br>
+    {<br>
+        ::pid_t pid = process->GetID();<br>
+        CFAllocatorRef alloc = kCFAllocatorDefault;<br>
+        watchdog.reset(::<wbr>BKSWatchdogAssertionCreateForP<wbr>ID(alloc, pid));<br>
+    }<br>
+#endif // #ifdef WITH_BKS<br>
+<br>
+    // Do we want to use a weak pointer to the NativeProcessDarwin here, in<br>
+    // which case we can guarantee we don't whack the process monitor if we<br>
+    // race between this thread and the main one on shutdown?<br>
+    while (IsExceptionPortValid())<br>
+    {<br>
+        ::pthread_testcancel();<br>
+<br>
+        MachException::Message exception_message;<br>
+<br>
+        if (num_exceptions_received > 0)<br>
+        {<br>
+            // We don't want a timeout here, just receive as many exceptions as<br>
+            // we can since we already have one.  We want to get all currently<br>
+            // available exceptions for this task at once.<br>
+            error = exception_message.Receive(<wbr>GetExceptionPort(),<br>
+                                              MACH_RCV_MSG | MACH_RCV_INTERRUPT<br>
+                                              | MACH_RCV_TIMEOUT, 0);<br>
+        }<br>
+        else if (periodic_timeout > 0)<br>
+        {<br>
+            // We need to stop periodically in this loop, so try and get a mach<br>
+            // message with a valid timeout (ms).<br>
+            error = exception_message.Receive(<wbr>GetExceptionPort(),<br>
+                                              MACH_RCV_MSG | MACH_RCV_INTERRUPT<br>
+                                              | MACH_RCV_TIMEOUT,<br>
+                                              periodic_timeout);<br>
+        }<br>
+        else<br>
+        {<br>
+            // We don't need to parse all current exceptions or stop<br>
+            // periodically, just wait for an exception forever.<br>
+            error = exception_message.Receive(<wbr>GetExceptionPort(),<br>
+                                              MACH_RCV_MSG | MACH_RCV_INTERRUPT,<br>
+                                              0);<br>
+        }<br>
+<br>
+        if (error.Success())<br>
+        {<br>
+            // We successfully received an exception.<br>
+            if (exception_message.<wbr>CatchExceptionRaise(task))<br>
+            {<br>
+                ++num_exceptions_received;<br>
+                ExceptionMessageReceived(<wbr>exception_message);<br>
+            }<br>
+        }<br>
+        else<br>
+        {<br>
+            if (error.GetError() == MACH_RCV_INTERRUPTED)<br>
+            {<br>
+                // We were interrupted.<br>
+<br>
+                // If we have no task port we should exit this thread, as it implies<br>
+                // the inferior went down.<br>
+                if (!IsExceptionPortValid())<br>
+                {<br>
+                    if (log)<br>
+                        log->Printf("<wbr>NativeProcessDarwin::%s(): the inferior "<br>
+                                    "exception port is no longer valid, "<br>
+                                    "canceling exception thread...", __FUNCTION__);<br>
+                    // Should we be setting a process state here?<br>
+                    break;<br>
+                }<br>
+<br>
+                // Make sure the inferior task is still valid.<br>
+                if (IsTaskValid())<br>
+                {<br>
+                    // Task is still ok.<br>
+                    if (log)<br>
+                        log->Printf("<wbr>NativeProcessDarwin::%s(): interrupted, but "<br>
+                                    "the inferior task iss till valid, "<br>
+                                    "continuing...", __FUNCTION__);<br>
+                    continue;<br>
+                }<br>
+                else<br>
+                {<br>
+                    // The inferior task is no longer valid.  Time to exit as<br>
+                    // the process has gone away.<br>
+                    if (log)<br>
+                        log->Printf("<wbr>NativeProcessDarwin::%s(): the inferior task "<br>
+                                    "has exited, and so will we...", __FUNCTION__);<br>
+                    // Does this race at all with our waitpid()?<br>
+                    SetState(eStateExited);<br>
+                    break;<br>
+                }<br>
+            }<br>
+            else if (error.GetError() == MACH_RCV_TIMED_OUT)<br>
+            {<br>
+                // We timed out when waiting for exceptions.<br>
+<br>
+                if (num_exceptions_received > 0)<br>
+                {<br>
+                    // We were receiving all current exceptions with a timeout of<br>
+                    // zero.  It is time to go back to our normal looping mode.<br>
+                    num_exceptions_received = 0;<br>
+<br>
+                    // Notify our main thread we have a complete exception message<br>
+                    // bundle available.  Get the possibly updated task port back<br>
+                    // from the process in case we exec'ed and our task port<br>
+                    // changed.<br>
+                    task = ExceptionMessageBundleComplete<wbr>();<br>
+<br>
+                    // In case we use a timeout value when getting exceptions,<br>
+                    // make sure our task is still valid.<br>
+                    if (IsTaskValid(task))<br>
+                    {<br>
+                        // Task is still ok.<br>
+                        if (log)<br>
+                            log->Printf("<wbr>NativeProcessDarwin::%s(): got a timeout, "<br>
+                                        "continuing...", __FUNCTION__);<br>
+                        continue;<br>
+                    }<br>
+                    else<br>
+                    {<br>
+                        // The inferior task is no longer valid.  Time to exit as<br>
+                        // the process has gone away.<br>
+                        if (log)<br>
+                            log->Printf("<wbr>NativeProcessDarwin::%s(): the inferior "<br>
+                                        "task has exited, and so will we...",<br>
+                                        __FUNCTION__);<br>
+                        // Does this race at all with our waitpid()?<br>
+                        SetState(eStateExited);<br>
+                        break;<br>
+                    }<br>
+                }<br>
+<br>
+#if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)<br>
+                if (watchdog.get())<br>
+                {<br>
+                    watchdog_elapsed += periodic_timeout;<br>
+                    if (watchdog_elapsed >= watchdog_timeout)<br>
+                    {<br>
+                        if (log)<br>
+                            log->Printf("<wbr>SBSWatchdogAssertionRenew(%p)"<wbr>,<br>
+                                        watchdog.get());<br>
+                        ::SBSWatchdogAssertionRenew (watchdog.get());<br>
+                        watchdog_elapsed = 0;<br>
+                    }<br>
+                }<br>
+#endif<br>
+            }<br>
+            else<br>
+            {<br>
+                if (log)<br>
+                    log->Printf("<wbr>NativeProcessDarwin::%s(): continuing after "<br>
+                                "receiving an unexpected error: %u (%s)",<br>
+                                __FUNCTION__, error.GetError(), error.AsCString());<br>
+                // TODO: notify of error?<br>
+            }<br>
+        }<br>
+    }<br>
+<br>
+#if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)<br>
+    if (watchdog.get())<br>
+    {<br>
+        // TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel when we<br>
+        // all are up and running on systems that support it. The SBS framework has a #define<br>
+        // that will forward SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel for now<br>
+        // so it should still build either way.<br>
+        DNBLogThreadedIf(LOG_TASK, "::<wbr>SBSWatchdogAssertionRelease(%<wbr>p)", watchdog.get());<br>
+        ::SBSWatchdogAssertionRelease (watchdog.get());<br>
+    }<br>
+#endif  // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)<br>
+<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeProcessDarwin::%s(%p): thread exiting...",<br>
+                    __FUNCTION__, this);<br>
+    return nullptr;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>StartExceptionThread()<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeProcessDarwin::%s() called", __FUNCTION__);<br>
+<br>
+    // Make sure we've looked up the inferior port.<br>
+    TaskPortForProcessID(error);<br>
+<br>
+    // Ensure the inferior task is valid.<br>
+    if (!IsTaskValid())<br>
+    {<br>
+        error.<wbr>SetErrorStringWithFormat("<wbr>cannot start exception thread: "<br>
+                                       "task 0x%4.4x is not valid", m_task);<br>
+        return error;<br>
+    }<br>
+<br>
+    // Get the mach port for the process monitor.<br>
+    mach_port_t task_self = mach_task_self();<br>
+<br>
+    // Allocate an exception port that we will use to track our child process<br>
+    auto mach_err = ::mach_port_allocate(task_<wbr>self, MACH_PORT_RIGHT_RECEIVE,<br>
+                                         &m_exception_port);<br>
+    error.SetError(mach_err, eErrorTypeMachKernel);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): mach_port_allocate("<br>
+                        "task_self=0x%4.4x, MACH_PORT_RIGHT_RECEIVE, "<br>
+                        "&m_exception_port) failed: %u (%s)", __FUNCTION__,<br>
+                        task_self, error.GetError(), error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    // Add the ability to send messages on the new exception port<br>
+    mach_err = ::mach_port_insert_right(task_<wbr>self, m_exception_port,<br>
+                                   m_exception_port, MACH_MSG_TYPE_MAKE_SEND);<br>
+    error.SetError(mach_err, eErrorTypeMachKernel);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): mach_port_insert_right("<br>
+                        "task_self=0x%4.4x, m_exception_port=0x%4.4x, "<br>
+                        "m_exception_port=0x%4.4x, MACH_MSG_TYPE_MAKE_SEND) "<br>
+                        "failed: %u (%s)", __FUNCTION__,<br>
+                        task_self, m_exception_port, m_exception_port,<br>
+                        error.GetError(), error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    // Save the original state of the exception ports for our child process.<br>
+    error = SaveExceptionPortInfo();<br>
+    if (error.Fail() || (m_exc_port_info.mask == 0))<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): SaveExceptionPortInfo() "<br>
+                        "failed, cannot install exception handler: %s",<br>
+                        __FUNCTION__, error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    // Set the ability to get all exceptions on this port.<br>
+    mach_err = ::task_set_exception_ports(m_<wbr>task, m_exc_port_info.mask,<br>
+                                          m_exception_port,<br>
+                                          EXCEPTION_DEFAULT |<br>
+                                          MACH_EXCEPTION_CODES,<br>
+                                          THREAD_STATE_NONE);<br>
+    error.SetError(mach_err, eErrorTypeMachKernel);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("::task_set_<wbr>exception_ports (task = 0x%4.4x, "<br>
+                        "exception_mask = 0x%8.8x, new_port = 0x%4.4x, "<br>
+                        "behavior = 0x%8.8x, new_flavor = 0x%8.8x) failed: "<br>
+                        "%u (%s)", m_task, m_exc_port_info.mask,<br>
+                        m_exception_port, (EXCEPTION_DEFAULT |<br>
+                                           MACH_EXCEPTION_CODES),<br>
+                        THREAD_STATE_NONE, error.GetError(),<br>
+                        error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    // Create the exception thread.<br>
+    auto pthread_err = ::pthread_create(&m_exception_<wbr>thread, nullptr,<br>
+                                        ExceptionThread, this);<br>
+    error.SetError(pthread_err, eErrorTypePOSIX);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): failed to create Mach "<br>
+                        "exception-handling thread: %u (%s)", __FUNCTION__,<br>
+                        error.GetError(), error.AsCString());<br>
+    }<br>
+<br>
+    return error;<br>
+}<br>
+<br>
+lldb::addr_t<br>
+NativeProcessDarwin::<wbr>GetDYLDAllImageInfosAddress(<wbr>Error &error) const<br>
+{<br>
+    error.Clear();<br>
+<br>
+    struct hack_task_dyld_info dyld_info;<br>
+    mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;<br>
+    // Make sure that COUNT isn't bigger than our hacked up struct<br>
+    // hack_task_dyld_info.  If it is, then make COUNT smaller to match.<br>
+    if (count > (sizeof(struct hack_task_dyld_info) / sizeof(natural_t)))<br>
+    {<br>
+        count = (sizeof(struct hack_task_dyld_info) / sizeof(natural_t));<br>
+    }<br>
+<br>
+    TaskPortForProcessID(error);<br>
+    if (error.Fail())<br>
+        return LLDB_INVALID_ADDRESS;<br>
+<br>
+    auto mach_err = ::task_info(m_task, TASK_DYLD_INFO, (task_info_t)&dyld_info,<br>
+                                &count);<br>
+    error.SetError(mach_err, eErrorTypeMachKernel);<br>
+    if (error.Success())<br>
+    {<br>
+        // We now have the address of the all image infos structure.<br>
+        return dyld_info.all_image_info_addr;<br>
+    }<br>
+<br>
+    // We don't have it.<br>
+    return LLDB_INVALID_ADDRESS;<br>
+}<br>
+<br>
+uint32_t<br>
+NativeProcessDarwin::<wbr>GetCPUTypeForLocalProcess(::<wbr>pid_t pid)<br>
+{<br>
+    int mib[CTL_MAXNAME] = {0, };<br>
+    size_t len = CTL_MAXNAME;<br>
+<br>
+    if (::sysctlnametomib("sysctl.<wbr>proc_cputype", mib, &len))<br>
+        return 0;<br>
+<br>
+    mib[len] = pid;<br>
+    len++;<br>
+<br>
+    cpu_type_t cpu;<br>
+    size_t cpu_len = sizeof(cpu);<br>
+    if (::sysctl (mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0))<br>
+        cpu = 0;<br>
+    return cpu;<br>
+}<br>
+<br>
+uint32_t<br>
+NativeProcessDarwin::<wbr>GetCPUType() const<br>
+{<br>
+    if (m_cpu_type == 0 && m_pid != 0)<br>
+        m_cpu_type = GetCPUTypeForLocalProcess(m_<wbr>pid);<br>
+    return m_cpu_type;<br>
+}<br>
+<br>
+task_t<br>
+NativeProcessDarwin::<wbr>ExceptionMessageBundleComplete<wbr>()<br>
+{<br>
+    // We have a complete bundle of exceptions for our child process.<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_exception_messages_<wbr>mutex);<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeProcessDarwin::%s(): processing %lu exception "<br>
+                    "messages.", __FUNCTION__, m_exception_messages.size());<br>
+<br>
+    if (m_exception_messages.empty())<br>
+    {<br>
+        // Not particularly useful...<br>
+        return m_task;<br>
+    }<br>
+<br>
+    bool auto_resume = false;<br>
+    m_did_exec = false;<br>
+<br>
+    // First check for any SIGTRAP and make sure we didn't exec<br>
+    const task_t task = m_task;<br>
+    size_t i;<br>
+    if (m_pid != 0)<br>
+    {<br>
+        bool received_interrupt = false;<br>
+        uint32_t num_task_exceptions = 0;<br>
+        for (i = 0; i < m_exception_messages.size(); ++i)<br>
+        {<br>
+            if (m_exception_messages[i].<wbr>state.task_port != task)<br>
+            {<br>
+                // This is an exception that is not for our inferior, ignore.<br>
+                continue;<br>
+            }<br>
+<br>
+            // This is an exception for the inferior.<br>
+            ++num_task_exceptions;<br>
+            const int signo = m_exception_messages[i].state.<wbr>SoftSignal();<br>
+            if (signo == SIGTRAP)<br>
+            {<br>
+                // SIGTRAP could mean that we exec'ed. We need to check the<br>
+                // dyld all_image_infos.infoArray to see if it is NULL and if<br>
+                // so, say that we exec'ed.<br>
+                const addr_t aii_addr =<br>
+                    GetDYLDAllImageInfosAddress(<wbr>error);<br>
+                if (aii_addr == LLDB_INVALID_ADDRESS)<br>
+                    break;<br>
+<br>
+                const addr_t info_array_count_addr = aii_addr + 4;<br>
+                uint32_t info_array_count = 0;<br>
+                size_t bytes_read = 0;<br>
+                Error read_error;<br>
+                read_error = ReadMemory(info_array_count_<wbr>addr,   // source addr<br>
+                                        &info_array_count,       // dest addr<br>
+                                        4,                       // byte count<br>
+                                        bytes_read);             // #bytes read<br>
+                if (read_error.Success() && (bytes_read == 4))<br>
+                {<br>
+                    if (info_array_count == 0)<br>
+                    {<br>
+                        // We got the all infos address, and there are zero<br>
+                        // entries.  We think we exec'd.<br>
+                        m_did_exec = true;<br>
+<br>
+                        // Force the task port to update itself in case the<br>
+                        // task port changed after exec<br>
+                        const task_t old_task = m_task;<br>
+                        const bool force_update = true;<br>
+                        const task_t new_task =<br>
+                            TaskPortForProcessID(error, force_update);<br>
+                        if (old_task != new_task)<br>
+                        {<br>
+                            if (log)<br>
+                                log->Printf("exec: inferior task port changed "<br>
+                                            "from 0x%4.4x to 0x%4.4x", old_task,<br>
+                                            new_task);<br>
+                        }<br>
+                    }<br>
+                }<br>
+                else<br>
+                {<br>
+                    if (log)<br>
+                        log->Printf("<wbr>NativeProcessDarwin::%s() warning: "<br>
+                                    "failed to read all_image_infos."<br>
+                                    "infoArrayCount from 0x%8.8llx",<br>
+                                    __FUNCTION__, info_array_count_addr);<br>
+                }<br>
+            }<br>
+            else if ((m_sent_interrupt_signo != 0) &&<br>
+                     (signo == m_sent_interrupt_signo))<br>
+            {<br>
+                // We just received the interrupt that we sent to ourselves.<br>
+                received_interrupt = true;<br>
+            }<br>
+        }<br>
+<br>
+        if (m_did_exec)<br>
+        {<br>
+            cpu_type_t process_cpu_type = GetCPUTypeForLocalProcess(m_<wbr>pid);<br>
+            if (m_cpu_type != process_cpu_type)<br>
+            {<br>
+                if (log)<br>
+                    log->Printf("<wbr>NativeProcessDarwin::%s(): arch changed from "<br>
+                                "0x%8.8x to 0x%8.8x", __FUNCTION__, m_cpu_type,<br>
+                                process_cpu_type);<br>
+                m_cpu_type = process_cpu_type;<br>
+                // TODO figure out if we need to do something here.<br>
+                // DNBArchProtocol::<wbr>SetArchitecture (process_cpu_type);<br>
+            }<br>
+            m_thread_list.Clear();<br>
+<br>
+            // TODO hook up breakpoints.<br>
+            // m_breakpoints.DisableAll();<br>
+        }<br>
+<br>
+        if (m_sent_interrupt_signo != 0)<br>
+        {<br>
+            if (received_interrupt)<br>
+            {<br>
+                if (log)<br>
+                    log->Printf("<wbr>NativeProcessDarwin::%s(): process "<br>
+                                "successfully interrupted with signal %i",<br>
+                                __FUNCTION__, m_sent_interrupt_signo);<br>
+<br>
+                // Mark that we received the interrupt signal<br>
+                m_sent_interrupt_signo = 0;<br>
+                // Now check if we had a case where:<br>
+                // 1 - We called NativeProcessDarwin::<wbr>Interrupt() but we stopped<br>
+                //     for another reason.<br>
+                // 2 - We called NativeProcessDarwin::Resume() (but still<br>
+                //     haven't gotten the interrupt signal).<br>
+                // 3 - We are now incorrectly stopped because we are handling<br>
+                //     the interrupt signal we missed.<br>
+                // 4 - We might need to resume if we stopped only with the<br>
+                //     interrupt signal that we never handled.<br>
+                if (m_auto_resume_signo != 0)<br>
+                {<br>
+                    // Only auto_resume if we stopped with _only_ the interrupt<br>
+                    // signal.<br>
+                    if (num_task_exceptions == 1)<br>
+                    {<br>
+                        auto_resume = true;<br>
+                        if (log)<br>
+                            log->Printf("<wbr>NativeProcessDarwin::%s(): auto "<br>
+                                        "resuming due to unhandled interrupt "<br>
+                                        "signal %i", __FUNCTION__,<br>
+                                        m_auto_resume_signo);<br>
+                    }<br>
+                    m_auto_resume_signo = 0;<br>
+                }<br>
+            }<br>
+            else<br>
+            {<br>
+                if (log)<br>
+                    log->Printf("<wbr>NativeProcessDarwin::%s(): didn't get signal "<br>
+                                "%i after MachProcess::Interrupt()",<br>
+                                __FUNCTION__, m_sent_interrupt_signo);<br>
+            }<br>
+        }<br>
+    }<br>
+<br>
+    // Let all threads recover from stopping and do any clean up based<br>
+    // on the previous thread state (if any).<br>
+    m_thread_list.ProcessDidStop(*<wbr>this);<br>
+<br>
+    // Let each thread know of any exceptions<br>
+    for (i = 0; i < m_exception_messages.size(); ++i)<br>
+    {<br>
+        // Let the thread list forward all exceptions on down to each thread.<br>
+        if (m_exception_messages[i].<wbr>state.task_port == task)<br>
+        {<br>
+            // This exception is for our inferior.<br>
+            m_thread_list.NotifyException(<wbr>m_exception_messages[i].state)<wbr>;<br>
+        }<br>
+<br>
+        if (log)<br>
+        {<br>
+            StreamString stream;<br>
+            m_exception_messages[i].Dump(<wbr>stream);<br>
+            stream.Flush();<br>
+            log->PutCString(stream.<wbr>GetString().c_str());<br>
+        }<br>
+    }<br>
+<br>
+    if (log)<br>
+    {<br>
+        StreamString stream;<br>
+        m_thread_list.Dump(stream);<br>
+        stream.Flush();<br>
+        log->PutCString(stream.<wbr>GetString().c_str());<br>
+    }<br>
+<br>
+    bool step_more = false;<br>
+    if (m_thread_list.ShouldStop(<wbr>step_more) && (auto_resume == false))<br>
+    {<br>
+        // TODO - need to hook up event system here. !!!!<br>
+#if 0<br>
+        // Wait for the eEventProcessRunningStateChang<wbr>ed event to be reset<br>
+        // before changing state to stopped to avoid race condition with<br>
+        // very fast start/stops.<br>
+        struct timespec timeout;<br>
+<br>
+        //DNBTimer::OffsetTimeOfDay(&<wbr>timeout, 0, 250 * 1000);   // Wait for 250 ms<br>
+        DNBTimer::OffsetTimeOfDay(&<wbr>timeout, 1, 0);  // Wait for 250 ms<br>
+        m_events.WaitForEventsToReset(<wbr>eEventProcessRunningStateChang<wbr>ed,<br>
+                                      &timeout);<br>
+#endif<br>
+        SetState(eStateStopped);<br>
+    }<br>
+    else<br>
+    {<br>
+        // Resume without checking our current state.<br>
+        PrivateResume();<br>
+    }<br>
+<br>
+    return m_task;<br>
+}<br>
+<br>
+void<br>
+NativeProcessDarwin::<wbr>StartSTDIOThread()<br>
+{<br>
+    // TODO implement<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>StartWaitpidThread(MainLoop &main_loop)<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    // Strategy: create a thread that sits on waitpid(), waiting for the<br>
+    // inferior process to die, reaping it in the process.  Arrange for<br>
+    // the thread to have a pipe file descriptor that it can send a byte<br>
+    // over when the waitpid completes.  Have the main loop have a read<br>
+    // object for the other side of the pipe, and have the callback for<br>
+    // the read do the process termination message sending.<br>
+<br>
+    // Create a single-direction communication channel.<br>
+    const bool child_inherits = false;<br>
+    error = m_waitpid_pipe.CreateNew(<wbr>child_inherits);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): failed to create waitpid "<br>
+                        "communication pipe: %s", __FUNCTION__,<br>
+                        error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    // Hook up the waitpid reader callback.<br>
+<br>
+    // TODO make PipePOSIX derive from IOObject.  This is goofy here.<br>
+    const bool transfer_ownership = false;<br>
+    auto io_sp = IOObjectSP(new File(m_waitpid_pipe.<wbr>GetReadFileDescriptor(),<br>
+                                     transfer_ownership));<br>
+    m_waitpid_reader_handle =<br>
+        main_loop.RegisterReadObject(<br>
+                          io_sp,<br>
+                          [this](MainLoopBase &){ HandleWaitpidResult(); },<br>
+                          error);<br>
+<br>
+    // Create the thread.<br>
+    auto pthread_err = ::pthread_create(&m_waitpid_<wbr>thread, nullptr,<br>
+                                        WaitpidThread, this);<br>
+    error.SetError(pthread_err, eErrorTypePOSIX);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): failed to create waitpid "<br>
+                        "handling thread: %u (%s)", __FUNCTION__,<br>
+                        error.GetError(), error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    return error;<br>
+}<br>
+<br>
+void*<br>
+NativeProcessDarwin::<wbr>WaitpidThread(void *arg)<br>
+{<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+    if (!arg)<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): cannot run waitpid "<br>
+                        "thread, mandatory process arg was null", __FUNCTION__);<br>
+        return nullptr;<br>
+    }<br>
+<br>
+    return reinterpret_cast<<wbr>NativeProcessDarwin*>(arg)-><wbr>DoWaitpidThread();<br>
+}<br>
+<br>
+void<br>
+NativeProcessDarwin::<wbr>MaybeRaiseThreadPriority()<br>
+{<br>
+#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)<br>
+    struct sched_param thread_param;<br>
+    int thread_sched_policy;<br>
+    if (pthread_getschedparam(<wbr>pthread_self(), &thread_sched_policy,<br>
+                              &thread_param) == 0)<br>
+    {<br>
+        thread_param.sched_priority = 47;<br>
+        pthread_setschedparam(pthread_<wbr>self(), thread_sched_policy,<br>
+                              &thread_param);<br>
+    }<br>
+#endif<br>
+}<br>
+<br>
+void*<br>
+NativeProcessDarwin::<wbr>DoWaitpidThread()<br>
+{<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    if (m_pid == LLDB_INVALID_PROCESS_ID)<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): inferior process ID is "<br>
+                        "not set, cannot waitpid on it", __FUNCTION__);<br>
+        return nullptr;<br>
+    }<br>
+<br>
+    // Name the thread.<br>
+    pthread_setname_np("waitpid thread");<br>
+<br>
+    // Ensure we don't get CPU starved.<br>
+    MaybeRaiseThreadPriority();<br>
+<br>
+    Error error;<br>
+    int status = -1;<br>
+<br>
+    while (1)<br>
+    {<br>
+        // Do a waitpid.<br>
+        ::pid_t child_pid = ::waitpid(m_pid, &status, 0);<br>
+        if (child_pid < 0)<br>
+            error.SetErrorToErrno();<br>
+        if (error.Fail())<br>
+        {<br>
+            if (error.GetError() == EINTR)<br>
+            {<br>
+                // This is okay, we can keep going.<br>
+                if (log)<br>
+                    log->Printf("<wbr>NativeProcessDarwin::%s(): waitpid(pid = %"<br>
+                                PRIu64 ", &status, 0) interrupted, continuing",<br>
+                                __FUNCTION__, m_pid);<br>
+                continue;<br>
+            }<br>
+<br>
+            // This error is not okay, abort.<br>
+            if (log)<br>
+                log->Printf("<wbr>NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64<br>
+                            ", &status, 0) aborting due to error: %u (%s)",<br>
+                            __FUNCTION__, m_pid, error.GetError(),<br>
+                            error.AsCString());<br>
+            break;<br>
+        }<br>
+<br>
+        // Log the successful result.<br>
+        if (log)<br>
+                log->Printf("<wbr>NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64<br>
+                            ", &status, 0) => %i, status = %i", __FUNCTION__,<br>
+                            m_pid, child_pid, status);<br>
+<br>
+        // Handle the result.<br>
+        if (WIFSTOPPED(status))<br>
+        {<br>
+            if (log)<br>
+                log->Printf("<wbr>NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64<br>
+                            ") received a stop, continuing waitpid() loop",<br>
+                            __FUNCTION__, m_pid);<br>
+            continue;<br>
+        }<br>
+        else // if (WIFEXITED(status) || WIFSIGNALED(status))<br>
+        {<br>
+            if (log)<br>
+                log->Printf("<wbr>NativeProcessDarwin::%s(pid = %" PRIu64 "): "<br>
+                            "waitpid thread is setting exit status for pid = "<br>
+                            "%i to %i", __FUNCTION__, m_pid,<br>
+                            child_pid, status);<br>
+<br>
+            error = SendInferiorExitStatusToMainLo<wbr>op(child_pid, status);<br>
+            return nullptr;<br>
+        }<br>
+    }<br>
+<br>
+    // We should never exit as long as our child process is alive.  If we<br>
+    // get here, something completely unexpected went wrong and we should exit.<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeProcessDarwin::%s(): internal error: waitpid thread "<br>
+                    "exited out of its main loop in an unexpected way. pid = %"<br>
+                    PRIu64 ". Sending exit status of -1.", __FUNCTION__, m_pid);<br>
+<br>
+    error = SendInferiorExitStatusToMainLo<wbr>op((::pid_t)m_pid, -1);<br>
+    return nullptr;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>SendInferiorExitStatusToMainLo<wbr>op(::pid_t pid, int status)<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    size_t bytes_written = 0;<br>
+<br>
+    // Send the pid.<br>
+    error = m_waitpid_pipe.Write(&pid, sizeof(pid), bytes_written);<br>
+    if (error.Fail() || (bytes_written < sizeof(pid)))<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s() - failed to write "<br>
+                        "waitpid exiting pid to the pipe.  Client will not "<br>
+                        "hear about inferior exit status!",<br>
+                        __FUNCTION__);<br>
+        return error;<br>
+    }<br>
+<br>
+    // Send the status.<br>
+    bytes_written = 0;<br>
+    error = m_waitpid_pipe.Write(&status, sizeof(status), bytes_written);<br>
+    if (error.Fail() || (bytes_written < sizeof(status)))<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s() - failed to write "<br>
+                        "waitpid exit result to the pipe.  Client will not "<br>
+                        "hear about inferior exit status!",<br>
+                        __FUNCTION__);<br>
+    }<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>HandleWaitpidResult()<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    // Read the pid.<br>
+    const bool notify_status = true;<br>
+<br>
+    ::pid_t pid = -1;<br>
+    size_t bytes_read = 0;<br>
+    error = m_waitpid_pipe.Read(&pid, sizeof(pid), bytes_read);<br>
+    if (error.Fail() || (bytes_read < sizeof(pid)))<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s() - failed to read "<br>
+                        "waitpid exiting pid from the pipe.  Will notify "<br>
+                        "as if parent process died with exit status -1.",<br>
+                        __FUNCTION__);<br>
+        SetExitStatus(<wbr>eExitTypeInvalid, -1, "failed to receive waitpid result",<br>
+                      notify_status);<br>
+        return error;<br>
+    }<br>
+<br>
+    // Read the status.<br>
+    int status = -1;<br>
+    error = m_waitpid_pipe.Read(&status, sizeof(status), bytes_read);<br>
+    if (error.Fail() || (bytes_read < sizeof(status)))<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s() - failed to read "<br>
+                        "waitpid exit status from the pipe.  Will notify "<br>
+                        "as if parent process died with exit status -1.",<br>
+                        __FUNCTION__);<br>
+        SetExitStatus(<wbr>eExitTypeInvalid, -1, "failed to receive waitpid result",<br>
+                      notify_status);<br>
+        return error;<br>
+    }<br>
+<br>
+    // Notify the monitor that our state has changed.<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeProcessDarwin::%s(): main loop received waitpid "<br>
+                    "exit status info: pid=%i (%s), status=%i",<br>
+                    __FUNCTION__, pid,<br>
+                    (pid == m_pid) ? "the inferior" : "not the inferior",<br>
+                    status);<br>
+<br>
+    ExitType exit_type = eExitTypeInvalid;<br>
+    int exit_status = -1;<br>
+<br>
+    if (WIFEXITED(status))<br>
+    {<br>
+        exit_type = eExitTypeExit;<br>
+        exit_status = WEXITSTATUS(status);<br>
+    }<br>
+    else if (WIFSIGNALED(status))<br>
+    {<br>
+        exit_type = eExitTypeSignal;<br>
+        exit_status = WTERMSIG(status);<br>
+    }<br>
+<br>
+    SetExitStatus(exit_type, exit_status, nullptr, notify_status);<br>
+    return error;<br>
+}<br>
+<br>
+task_t<br>
+NativeProcessDarwin::<wbr>TaskPortForProcessID(Error &error, bool force) const<br>
+{<br>
+    if ((m_task == TASK_NULL) || force)<br>
+    {<br>
+        Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+        if (m_pid == LLDB_INVALID_PROCESS_ID)<br>
+        {<br>
+            if (log)<br>
+                log->Printf("<wbr>NativeProcessDarwin::%s(): cannot get task due "<br>
+                            "to invalid pid", __FUNCTION__);<br>
+            return TASK_NULL;<br>
+        }<br>
+<br>
+        const uint32_t num_retries = 10;<br>
+        const uint32_t usec_interval = 10000;<br>
+<br>
+        mach_port_t task_self = mach_task_self();<br>
+        task_t task = TASK_NULL;<br>
+<br>
+        for (uint32_t i = 0; i < num_retries; i++)<br>
+        {<br>
+            kern_return_t err = ::task_for_pid(task_self, m_pid, &task);<br>
+            if (err == 0)<br>
+            {<br>
+                // Succeeded.  Save and return it.<br>
+                error.Clear();<br>
+                m_task = task;<br>
+                log->Printf("<wbr>NativeProcessDarwin::%s(): ::task_for_pid("<br>
+                            "stub_port = 0x%4.4x, pid = %llu, &task) "<br>
+                            "succeeded: inferior task port = 0x%4.4x",<br>
+                            __FUNCTION__, task_self, m_pid, m_task);<br>
+                return m_task;<br>
+            }<br>
+            else<br>
+            {<br>
+                // Failed to get the task for the inferior process.<br>
+                error.SetError(err, eErrorTypeMachKernel);<br>
+                if (log)<br>
+                {<br>
+                    log->Printf("<wbr>NativeProcessDarwin::%s(): ::task_for_pid("<br>
+                                "stub_port = 0x%4.4x, pid = %llu, &task) "<br>
+                                "failed, err = 0x%8.8x (%s)",<br>
+                                __FUNCTION__, task_self,<br>
+                                m_pid,<br>
+                                err,<br>
+                                error.AsCString());<br>
+                }<br>
+            }<br>
+<br>
+            // Sleep a bit and try again<br>
+            ::usleep (usec_interval);<br>
+        }<br>
+<br>
+        // We failed to get the task for the inferior process.<br>
+        // Ensure that it is cleared out.<br>
+        m_task = TASK_NULL;<br>
+    }<br>
+    return m_task;<br>
+}<br>
+<br>
+void<br>
+NativeProcessDarwin::<wbr>AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,<br>
+                                      Error &error)<br>
+{<br>
+    error.SetErrorString("TODO: implement");<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>PrivateResume()<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_exception_messages_<wbr>mutex);<br>
+    m_auto_resume_signo = m_sent_interrupt_signo;<br>
+<br>
+    if (log)<br>
+    {<br>
+        if (m_auto_resume_signo)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): task 0x%x resuming (with "<br>
+                        "unhandled interrupt signal %i)...", __FUNCTION__,<br>
+                        m_task, m_auto_resume_signo);<br>
+        else<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): task 0x%x resuming...",<br>
+                        __FUNCTION__, m_task);<br>
+    }<br>
+<br>
+    error = ReplyToAllExceptions();<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): aborting, failed to "<br>
+                        "reply to exceptions: %s", __FUNCTION__,<br>
+                        error.AsCString());<br>
+        return error;<br>
+    }<br>
+    //    bool stepOverBreakInstruction = step;<br>
+<br>
+    // Let the thread prepare to resume and see if any threads want us to<br>
+    // step over a breakpoint instruction (ProcessWillResume will modify<br>
+    // the value of stepOverBreakInstruction).<br>
+    m_thread_list.<wbr>ProcessWillResume(*this, m_thread_actions);<br>
+<br>
+    // Set our state accordingly<br>
+    if (m_thread_actions.<wbr>NumActionsWithState(<wbr>eStateStepping))<br>
+        SetState(eStateStepping);<br>
+    else<br>
+        SetState(eStateRunning);<br>
+<br>
+    // Now resume our task.<br>
+    error = ResumeTask();<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>ReplyToAllExceptions()<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                      LIBLLDB_LOG_VERBOSE));<br>
+<br>
+    TaskPortForProcessID(error);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): no task port, aborting",<br>
+                        __FUNCTION__);<br>
+        return error;<br>
+    }<br>
+<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_exception_messages_<wbr>mutex);<br>
+    if (m_exception_messages.empty())<br>
+    {<br>
+        // We're done.<br>
+        return error;<br>
+    }<br>
+<br>
+    size_t index = 0;<br>
+    for (auto &message : m_exception_messages)<br>
+    {<br>
+        if (log)<br>
+        {<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): replying to exception "<br>
+                        "%zu...", __FUNCTION__, index++);<br>
+        }<br>
+<br>
+        int thread_reply_signal = 0;<br>
+<br>
+        const tid_t tid =<br>
+            m_thread_list.<wbr>GetThreadIDByMachPortNumber(<wbr>message.state<br>
+                                                      .thread_port);<br>
+        const ResumeAction *action = nullptr;<br>
+        if (tid != LLDB_INVALID_THREAD_ID)<br>
+            action = m_thread_actions.<wbr>GetActionForThread (tid, false);<br>
+<br>
+        if (action)<br>
+        {<br>
+            thread_reply_signal = action->signal;<br>
+            if (thread_reply_signal)<br>
+                m_thread_actions.<wbr>SetSignalHandledForThread(tid)<wbr>;<br>
+        }<br>
+<br>
+        error = message.Reply(m_pid, m_task, thread_reply_signal);<br>
+        if (error.Fail() && log)<br>
+        {<br>
+            // We log any error here, but we don't stop the exception<br>
+            // response handling.<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): failed to reply to "<br>
+                        "exception: %s", __FUNCTION__, error.AsCString());<br>
+            error.Clear();<br>
+        }<br>
+    }<br>
+<br>
+    // Erase all exception message as we should have used and replied<br>
+    // to them all already.<br>
+    m_exception_messages.clear();<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>ResumeTask()<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    TaskPortForProcessID(error);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): failed to get task port "<br>
+                        "for process when attempting to resume: %s",<br>
+                        __FUNCTION__, error.AsCString());<br>
+        return error;<br>
+    }<br>
+    if (m_task == TASK_NULL)<br>
+    {<br>
+        error.SetErrorString("task port retrieval succeeded but task port is "<br>
+                             "null when attempting to resume the task");<br>
+        return error;<br>
+    }<br>
+<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeProcessDarwin::%s(): requesting resume of task "<br>
+                    "0x%4.4x", __FUNCTION__, m_task);<br>
+<br>
+    // Get the BasicInfo struct to verify that we're suspended before we try<br>
+    // to resume the task.<br>
+    struct task_basic_info task_info;<br>
+    error = GetTaskBasicInfo(m_task, &task_info);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): failed to get task "<br>
+                        "BasicInfo when attempting to resume: %s",<br>
+                        __FUNCTION__, error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    // task_resume isn't counted like task_suspend calls are, so if the<br>
+    // task is not suspended, don't try and resume it since it is already<br>
+    // running<br>
+    if (task_info.suspend_count > 0)<br>
+    {<br>
+        auto mach_err = ::task_resume(m_task);<br>
+        error.SetError(mach_err, eErrorTypeMachKernel);<br>
+        if (log)<br>
+        {<br>
+            if (error.Success())<br>
+                log->Printf("::task_resume(<wbr>target_task = 0x%4.4x): success",<br>
+                            m_task);<br>
+            else<br>
+                log->Printf("::task_resume(<wbr>target_task = 0x%4.4x) error: %s",<br>
+                            m_task, error.AsCString());<br>
+        }<br>
+    }<br>
+    else<br>
+    {<br>
+        if (log)<br>
+            log->Printf("::task_resume(<wbr>target_task = 0x%4.4x): ignored, "<br>
+                        "already running", m_task);<br>
+    }<br>
+<br>
+    return error;<br>
+}<br>
+<br>
+bool<br>
+NativeProcessDarwin::<wbr>IsTaskValid() const<br>
+{<br>
+    if (m_task == TASK_NULL)<br>
+        return false;<br>
+<br>
+    struct task_basic_info task_info;<br>
+    return GetTaskBasicInfo(m_task, &task_info).Success();<br>
+}<br>
+<br>
+bool<br>
+NativeProcessDarwin::<wbr>IsTaskValid(task_t task) const<br>
+{<br>
+    if (task == TASK_NULL)<br>
+        return false;<br>
+<br>
+    struct task_basic_info task_info;<br>
+    return GetTaskBasicInfo(task, &task_info).Success();<br>
+}<br>
+<br>
+mach_port_t<br>
+NativeProcessDarwin::<wbr>GetExceptionPort() const<br>
+{<br>
+    return m_exception_port;<br>
+}<br>
+<br>
+bool<br>
+NativeProcessDarwin::<wbr>IsExceptionPortValid () const<br>
+{<br>
+    return MACH_PORT_VALID(m_exception_<wbr>port);<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>GetTaskBasicInfo(task_t task,<br>
+                                      struct task_basic_info *info) const<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    // Validate args.<br>
+    if (info == NULL)<br>
+    {<br>
+        error.<wbr>SetErrorStringWithFormat("<wbr>NativeProcessDarwin::%s(): mandatory "<br>
+                                       "info arg is null", __FUNCTION__);<br>
+        return error;<br>
+    }<br>
+<br>
+    // Grab the task if we don't already have it.<br>
+    if (task == TASK_NULL)<br>
+    {<br>
+        error.<wbr>SetErrorStringWithFormat("<wbr>NativeProcessDarwin::%s(): given task "<br>
+                                       "is invalid", __FUNCTION__);<br>
+    }<br>
+<br>
+    mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;<br>
+    auto err = ::task_info(m_task, TASK_BASIC_INFO, (task_info_t)info, &count);<br>
+    error.SetError(err, eErrorTypeMachKernel);<br>
+    if (error.Fail())<br>
+    {<br>
+        if (log)<br>
+            log->Printf("::task_info(<wbr>target_task = 0x%4.4x, "<br>
+                        "flavor = TASK_BASIC_INFO, task_info_out => %p, "<br>
+                        "task_info_outCnt => %u) failed: %u (%s)", m_task, info,<br>
+                        count, error.GetError(), error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    Log *verbose_log(<wbr>GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS |<br>
+                                              LIBLLDB_LOG_VERBOSE));<br>
+    if (verbose_log)<br>
+    {<br>
+        float user = (float)info->user_time.seconds +<br>
+            (float)info->user_time.<wbr>microseconds / 1000000.0f;<br>
+        float system = (float)info->user_time.seconds +<br>
+            (float)info->user_time.<wbr>microseconds / 1000000.0f;<br>
+        verbose_log->Printf("task_<wbr>basic_info = { suspend_count = %i, "<br>
+                            "virtual_size = 0x%8.8llx, resident_size = "<br>
+                            "0x%8.8llx, user_time = %f, system_time = %f }",<br>
+                            info->suspend_count,<br>
+                            (uint64_t)info->virtual_size,<br>
+                            (uint64_t)info->resident_size,<br>
+                            user, system);<br>
+    }<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>SuspendTask()<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    if (m_task == TASK_NULL)<br>
+    {<br>
+        error.SetErrorString("task port is null, cannot suspend task");<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s() failed: %s",<br>
+                        __FUNCTION__, error.AsCString());<br>
+        return error;<br>
+    }<br>
+<br>
+    auto mach_err = ::task_suspend(m_task);<br>
+    error.SetError(mach_err, eErrorTypeMachKernel);<br>
+    if (error.Fail() && log)<br>
+        log->Printf("::task_suspend(<wbr>target_task = 0x%4.4x)", m_task);<br>
+<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::Resume(<wbr>const ResumeActionList &resume_actions)<br>
+{<br>
+    Error error;<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_PROCESS));<br>
+<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeProcessDarwin::%s() called", __FUNCTION__);<br>
+<br>
+    if (CanResume())<br>
+    {<br>
+        m_thread_actions = resume_actions;<br>
+        error = PrivateResume();<br>
+        return error;<br>
+    }<br>
+<br>
+    auto state = GetState();<br>
+    if (state == eStateRunning)<br>
+    {<br>
+        if (log)<br>
+            log->Printf("<wbr>NativeProcessDarwin::%s(): task 0x%x is already "<br>
+                        "running, ignoring...", __FUNCTION__,<br>
+                        TaskPortForProcessID(error));<br>
+        return error;<br>
+    }<br>
+<br>
+    // We can't resume from this state.<br>
+    error.<wbr>SetErrorStringWithFormat("task 0x%x has state %s, can't resume",<br>
+                                   TaskPortForProcessID(error),<br>
+                                   StateAsCString(state));<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::Halt()<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::Detach()<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::Signal(<wbr>int signo)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>Interrupt()<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::Kill()<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>GetMemoryRegionInfo(lldb::<wbr>addr_t load_addr,<br>
+                                         MemoryRegionInfo &range_info)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>ReadMemory(lldb::addr_t addr, void *buf, size_t size,<br>
+                                size_t &bytes_read)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>ReadMemoryWithoutTrap(lldb::<wbr>addr_t addr, void *buf,<br>
+                                           size_t size, size_t &bytes_read)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>WriteMemory(lldb::addr_t addr, const void *buf,<br>
+                                 size_t size, size_t &bytes_written)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>AllocateMemory(size_t size, uint32_t permissions,<br>
+                                    lldb::addr_t &addr)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>DeallocateMemory(lldb::addr_t addr)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+lldb::addr_t<br>
+NativeProcessDarwin::<wbr>GetSharedLibraryInfoAddress()<br>
+{<br>
+    return LLDB_INVALID_ADDRESS;<br>
+}<br>
+<br>
+size_t<br>
+NativeProcessDarwin::<wbr>UpdateThreads()<br>
+{<br>
+    return 0;<br>
+}<br>
+<br>
+bool<br>
+NativeProcessDarwin::<wbr>GetArchitecture(ArchSpec &arch) const<br>
+{<br>
+    return false;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>SetBreakpoint(lldb::addr_t addr, uint32_t size,<br>
+                                   bool hardware)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+void<br>
+NativeProcessDarwin::<wbr>DoStopIDBumped(uint32_t newBumpId)<br>
+{<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>GetLoadedModuleFileSpec(const char* module_path,<br>
+                                             FileSpec& file_spec)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeProcessDarwin::<wbr>GetFileLoadAddress(const llvm::StringRef& file_name,<br>
+                                        lldb::addr_t& load_addr)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
+<br>
+// ------------------------------<wbr>------------------------------<wbr>-----<br>
+// NativeProcessProtocol protected interface<br>
+// ------------------------------<wbr>------------------------------<wbr>-----<br>
+Error<br>
+NativeProcessDarwin::<wbr>GetSoftwareBreakpointTrapOpcod<wbr>e(size_t<br>
+                                                     trap_opcode_size_hint,<br>
+                                                     size_t &actual_opcode_size,<br>
+                                                     const uint8_t<br>
+                                                     *&trap_opcode_bytes)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("TODO: implement");<br>
+    return error;<br>
+}<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeProcessDarwin.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/NativeProcessDarwin.h?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>NativeProcessDarwin.h?rev=<wbr>280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeProcessDarwin.h (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeProcessDarwin.h Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,479 @@<br>
+//===-- NativeProcessDarwin.h ------------------------------<wbr>--- -*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef NativeProcessDarwin_h<br>
+#define NativeProcessDarwin_h<br>
+<br>
+// NOTE: this code should only be compiled on Apple Darwin systems.  It is<br>
+// not cross-platform code and is not intended to build on any other platform.<br>
+// Therefore, platform-specific headers and code are okay here.<br>
+<br>
+// C includes<br>
+#include <mach/mach_types.h><br>
+<br>
+// C++ includes<br>
+#include <mutex><br>
+#include <unordered_set><br>
+<br>
+// Other libraries and framework includes<br>
+#include "lldb/Core/ArchSpec.h"<br>
+#include "lldb/lldb-types.h"<br>
+#include "lldb/Host/common/<wbr>NativeProcessProtocol.h"<br>
+#include "lldb/Host/Debug.h"<br>
+#include "lldb/Host/FileSpec.h"<br>
+#include "lldb/Host/HostThread.h"<br>
+#include "lldb/Host/Pipe.h"<br>
+#include "lldb/Target/MemoryRegionInfo.<wbr>h"<br>
+<br>
+#include "NativeThreadListDarwin.h"<br>
+#include "LaunchFlavor.h"<br>
+#include "MachException.h"<br>
+#include "NativeThreadDarwin.h"<br>
+<br>
+namespace lldb_private {<br>
+    class Error;<br>
+    class Scalar;<br>
+<br>
+    namespace process_darwin {<br>
+<br>
+        /// @class NativeProcessDarwin<br>
+        /// @brief Manages communication with the inferior (debugee) process.<br>
+        ///<br>
+        /// Upon construction, this class prepares and launches an inferior<br>
+        /// process for debugging.<br>
+        ///<br>
+        /// Changes in the inferior process state are broadcasted.<br>
+        class NativeProcessDarwin: public NativeProcessProtocol<br>
+        {<br>
+            friend Error<br>
+            NativeProcessProtocol::Launch(<wbr>ProcessLaunchInfo &launch_info,<br>
+                                          NativeDelegate &native_delegate,<br>
+                                          MainLoop &mainloop,<br>
+                                          NativeProcessProtocolSP &process_sp);<br>
+<br>
+            friend Error<br>
+            NativeProcessProtocol::Attach(<wbr>lldb::pid_t pid,<br>
+                                          NativeProcessProtocol::<wbr>NativeDelegate<br>
+                                          &native_delegate,<br>
+                                          MainLoop &mainloop,<br>
+                                          NativeProcessProtocolSP &process_sp);<br>
+<br>
+        public:<br>
+<br>
+            ~NativeProcessDarwin() override;<br>
+<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            // NativeProcessProtocol Interface<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            Error<br>
+            Resume(const ResumeActionList &resume_actions) override;<br>
+<br>
+            Error<br>
+            Halt() override;<br>
+<br>
+            Error<br>
+            Detach() override;<br>
+<br>
+            Error<br>
+            Signal(int signo) override;<br>
+<br>
+            Error<br>
+            Interrupt() override;<br>
+<br>
+            Error<br>
+            Kill() override;<br>
+<br>
+            Error<br>
+            GetMemoryRegionInfo(lldb::<wbr>addr_t load_addr, MemoryRegionInfo<br>
+                                &range_info) override;<br>
+<br>
+            Error<br>
+            ReadMemory(lldb::addr_t addr, void *buf, size_t size,<br>
+                       size_t &bytes_read) override;<br>
+<br>
+            Error<br>
+            ReadMemoryWithoutTrap(lldb::<wbr>addr_t addr, void *buf, size_t size,<br>
+                                  size_t &bytes_read) override;<br>
+<br>
+            Error<br>
+            WriteMemory(lldb::addr_t addr, const void *buf, size_t size,<br>
+                        size_t &bytes_written) override;<br>
+<br>
+            Error<br>
+            AllocateMemory(size_t size, uint32_t permissions,<br>
+                           lldb::addr_t &addr) override;<br>
+<br>
+            Error<br>
+            DeallocateMemory(lldb::addr_t addr) override;<br>
+<br>
+            lldb::addr_t<br>
+            GetSharedLibraryInfoAddress() override;<br>
+<br>
+            size_t<br>
+            UpdateThreads() override;<br>
+<br>
+            bool<br>
+            GetArchitecture(ArchSpec &arch) const override;<br>
+<br>
+            Error<br>
+            SetBreakpoint(lldb::addr_t addr, uint32_t size,<br>
+                          bool hardware) override;<br>
+<br>
+            void<br>
+            DoStopIDBumped(uint32_t newBumpId) override;<br>
+<br>
+            Error<br>
+            GetLoadedModuleFileSpec(const char* module_path,<br>
+                                    FileSpec& file_spec) override;<br>
+<br>
+            Error<br>
+            GetFileLoadAddress(const llvm::StringRef& file_name,<br>
+                               lldb::addr_t& load_addr) override;<br>
+<br>
+            NativeThreadDarwinSP<br>
+            GetThreadByID(lldb::tid_t id);<br>
+<br>
+            task_t<br>
+            GetTask() const<br>
+            {<br>
+                return m_task;<br>
+            }<br>
+<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            // Interface used by NativeRegisterContext-derived classes.<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            static Error<br>
+            PtraceWrapper(int req,<br>
+                          lldb::pid_t pid,<br>
+                          void *addr = nullptr,<br>
+                          void *data = nullptr,<br>
+                          size_t data_size = 0,<br>
+                          long *result = nullptr);<br>
+<br>
+            bool<br>
+            SupportHardwareSingleStepping(<wbr>) const;<br>
+<br>
+        protected:<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            // NativeProcessProtocol protected interface<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            Error<br>
+            GetSoftwareBreakpointTrapOpcod<wbr>e(size_t trap_opcode_size_hint,<br>
+                                            size_t &actual_opcode_size,<br>
+                                            const uint8_t *&trap_opcode_bytes)<br>
+            override;<br>
+<br>
+        private:<br>
+<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            /// Mach task-related Member Variables<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+<br>
+            // The task port for the inferior process.<br>
+            mutable task_t  m_task;<br>
+<br>
+            // True if the inferior process did an exec since we started<br>
+            // monitoring it.<br>
+            bool  m_did_exec;<br>
+<br>
+            // The CPU type of this process.<br>
+            mutable cpu_type_t  m_cpu_type;<br>
+<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            /// Exception/Signal Handling Member Variables<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+<br>
+            // Exception port on which we will receive child exceptions<br>
+            mach_port_t  m_exception_port;<br>
+<br>
+            // Saved state of the child exception port prior to us installing<br>
+            // our own intercepting port.<br>
+            MachException::PortInfo  m_exc_port_info;<br>
+<br>
+            // The thread that runs the Mach exception read and reply handler.<br>
+            pthread_t  m_exception_thread;<br>
+<br>
+            // TODO see if we can remove this if we get the exception collection<br>
+            // and distribution to happen in a single-threaded fashion.<br>
+            std::recursive_mutex  m_exception_messages_mutex;<br>
+<br>
+            // A collection of exception messages caught when listening to the<br>
+            // exception port.<br>
+            MachException::Message::<wbr>collection  m_exception_messages;<br>
+<br>
+            // When we call MachProcess::Interrupt(), we want to send this<br>
+            // signal (if non-zero).<br>
+            int  m_sent_interrupt_signo;<br>
+<br>
+            // If we resume the process and still haven't received our<br>
+            // interrupt signal (if this is non-zero).<br>
+            int  m_auto_resume_signo;<br>
+<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            /// Thread-related Member Variables<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            NativeThreadListDarwin  m_thread_list;<br>
+            ResumeActionList        m_thread_actions;<br>
+<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            /// Process Lifetime Member Variable<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+<br>
+            // The pipe over which the waitpid thread and the main loop will<br>
+            // communicate.<br>
+            Pipe  m_waitpid_pipe;<br>
+<br>
+            // The thread that runs the waitpid handler.<br>
+            pthread_t  m_waitpid_thread;<br>
+<br>
+            // waitpid reader callback handle.<br>
+            MainLoop::ReadHandleUP m_waitpid_reader_handle;<br>
+<br>
+#if 0<br>
+            ArchSpec m_arch;<br>
+<br>
+            LazyBool m_supports_mem_region;<br>
+            std::vector<MemoryRegionInfo> m_mem_region_cache;<br>
+<br>
+            lldb::tid_t m_pending_notification_tid;<br>
+<br>
+            // List of thread ids stepping with a breakpoint with the address of<br>
+            // the relevan breakpoint<br>
+            std::map<lldb::tid_t, lldb::addr_t><br>
+            m_threads_stepping_with_<wbr>breakpoint;<br>
+#endif<br>
+<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            // Private Instance Methods<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            NativeProcessDarwin(lldb::pid_<wbr>t pid, int pty_master_fd);<br>
+<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            /// Finalize the launch.<br>
+            ///<br>
+            /// This method associates the NativeProcessDarwin instance with<br>
+            /// the host process that was just launched.  It peforms actions<br>
+            /// like attaching a listener to the inferior exception port,<br>
+            /// ptracing the process, and the like.<br>
+            ///<br>
+            /// @param[in] launch_flavor<br>
+            ///     The launch flavor that was used to launch the process.<br>
+            ///<br>
+            /// @param[in] main_loop<br>
+            ///     The main loop that will run the process monitor.  Work<br>
+            ///     that needs to be done (e.g. reading files) gets registered<br>
+            ///     here along with callbacks to process the work.<br>
+            ///<br>
+            /// @return<br>
+            ///     Any error that occurred during the aforementioned<br>
+            ///     operations.  Failure here will force termination of the<br>
+            ///     launched process and debugging session.<br>
+            // ------------------------------<wbr>------------------------------<wbr>-----<br>
+            Error<br>
+            FinalizeLaunch(LaunchFlavor launch_flavor, MainLoop &main_loop);<br>
+<br>
+            Error<br>
+            SaveExceptionPortInfo();<br>
+<br>
+            void<br>
+            ExceptionMessageReceived(const MachException::Message &message);<br>
+<br>
+            void<br>
+            MaybeRaiseThreadPriority();<br>
+<br>
+            Error<br>
+            StartExceptionThread();<br>
+<br>
+            Error<br>
+            SendInferiorExitStatusToMainLo<wbr>op(::pid_t pid, int status);<br>
+<br>
+            Error<br>
+            HandleWaitpidResult();<br>
+<br>
+            bool<br>
+            ProcessUsingSpringBoard() const;<br>
+<br>
+            bool<br>
+            ProcessUsingBackBoard() const;<br>
+<br>
+            static void*<br>
+            ExceptionThread(void *arg);<br>
+<br>
+            void*<br>
+            DoExceptionThread();<br>
+<br>
+            lldb::addr_t<br>
+            GetDYLDAllImageInfosAddress(<wbr>Error &error) const;<br>
+<br>
+            static uint32_t<br>
+            GetCPUTypeForLocalProcess(::<wbr>pid_t pid);<br>
+<br>
+            uint32_t<br>
+            GetCPUType() const;<br>
+<br>
+            task_t<br>
+            ExceptionMessageBundleComplete<wbr>();<br>
+<br>
+            void<br>
+            StartSTDIOThread();<br>
+<br>
+            Error<br>
+            StartWaitpidThread(MainLoop &main_loop);<br>
+<br>
+            static void*<br>
+            WaitpidThread(void *arg);<br>
+<br>
+            void*<br>
+            DoWaitpidThread();<br>
+<br>
+            task_t<br>
+            TaskPortForProcessID(Error &error, bool force = false) const;<br>
+<br>
+            /// Attaches to an existing process.  Forms the<br>
+            /// implementation of Process::DoAttach.<br>
+            void<br>
+            AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Error &error);<br>
+<br>
+            ::pid_t<br>
+            Attach(lldb::pid_t pid, Error &error);<br>
+<br>
+            Error<br>
+            PrivateResume();<br>
+<br>
+            Error<br>
+            ReplyToAllExceptions();<br>
+<br>
+            Error<br>
+            ResumeTask();<br>
+<br>
+            bool<br>
+            IsTaskValid() const;<br>
+<br>
+            bool<br>
+            IsTaskValid(task_t task) const;<br>
+<br>
+            mach_port_t<br>
+            GetExceptionPort() const;<br>
+<br>
+            bool<br>
+            IsExceptionPortValid () const;<br>
+<br>
+            Error<br>
+            GetTaskBasicInfo(task_t task, struct task_basic_info *info) const;<br>
+<br>
+            Error<br>
+            SuspendTask();<br>
+<br>
+            static Error<br>
+            SetDefaultPtraceOpts(const lldb::pid_t);<br>
+<br>
+            static void *<br>
+            MonitorThread(void *baton);<br>
+<br>
+            void<br>
+            MonitorCallback(lldb::pid_t pid, bool exited, int signal,<br>
+                            int status);<br>
+<br>
+            void<br>
+            WaitForNewThread(::pid_t tid);<br>
+<br>
+            void<br>
+            MonitorSIGTRAP(const siginfo_t &info, NativeThreadDarwin &thread);<br>
+<br>
+            void<br>
+            MonitorTrace(<wbr>NativeThreadDarwin &thread);<br>
+<br>
+            void<br>
+            MonitorBreakpoint(<wbr>NativeThreadDarwin &thread);<br>
+<br>
+            void<br>
+            MonitorWatchpoint(<wbr>NativeThreadDarwin &thread, uint32_t wp_index);<br>
+<br>
+            void<br>
+            MonitorSignal(const siginfo_t &info, NativeThreadDarwin &thread,<br>
+                          bool exited);<br>
+<br>
+            Error<br>
+            SetupSoftwareSingleStepping(<wbr>NativeThreadDarwin &thread);<br>
+<br>
+#if 0<br>
+            static ::ProcessMessage::CrashReason<br>
+            GetCrashReasonForSIGSEGV(const siginfo_t *info);<br>
+<br>
+            static ::ProcessMessage::CrashReason<br>
+            GetCrashReasonForSIGILL(const siginfo_t *info);<br>
+<br>
+            static ::ProcessMessage::CrashReason<br>
+            GetCrashReasonForSIGFPE(const siginfo_t *info);<br>
+<br>
+            static ::ProcessMessage::CrashReason<br>
+            GetCrashReasonForSIGBUS(const siginfo_t *info);<br>
+#endif<br>
+<br>
+            bool<br>
+            HasThreadNoLock(lldb::tid_t thread_id);<br>
+<br>
+            bool<br>
+            StopTrackingThread(lldb::tid_t thread_id);<br>
+<br>
+            NativeThreadDarwinSP<br>
+            AddThread(lldb::tid_t thread_id);<br>
+<br>
+            Error<br>
+            GetSoftwareBreakpointPCOffset(<wbr>uint32_t &actual_opcode_size);<br>
+<br>
+            Error<br>
+            FixupBreakpointPCAsNeeded(<wbr>NativeThreadDarwin &thread);<br>
+<br>
+            /// Writes a siginfo_t structure corresponding to the given thread<br>
+            /// ID to the memory region pointed to by @p siginfo.<br>
+            Error<br>
+            GetSignalInfo(lldb::tid_t tid, void *siginfo);<br>
+<br>
+            /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)<br>
+            /// corresponding to the given thread ID to the memory pointed to<br>
+            /// by @p message.<br>
+            Error<br>
+            GetEventMessage(lldb::tid_t tid, unsigned long *message);<br>
+<br>
+            void<br>
+            NotifyThreadDeath(lldb::tid_t tid);<br>
+<br>
+            Error<br>
+            Detach(lldb::tid_t tid);<br>
+<br>
+<br>
+            // This method is requests a stop on all threads which are still<br>
+            // running. It sets up a deferred delegate notification, which will<br>
+            // fire once threads report as stopped. The triggerring_tid will be<br>
+            // set as the current thread (main stop reason).<br>
+            void<br>
+            StopRunningThreads(lldb::tid_t triggering_tid);<br>
+<br>
+            // Notify the delegate if all threads have stopped.<br>
+            void SignalIfAllThreadsStopped();<br>
+<br>
+            // Resume the given thread, optionally passing it the given signal.<br>
+            // The type of resume operation (continue, single-step) depends on<br>
+            // the state parameter.<br>
+            Error<br>
+            ResumeThread(<wbr>NativeThreadDarwin &thread, lldb::StateType state,<br>
+                         int signo);<br>
+<br>
+            void<br>
+            ThreadWasCreated(<wbr>NativeThreadDarwin &thread);<br>
+<br>
+            void<br>
+            SigchldHandler();<br>
+        };<br>
+<br>
+    } // namespace process_darwin<br>
+} // namespace lldb_private<br>
+<br>
+#endif /* NativeProcessDarwin_h */<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadDarwin.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>NativeThreadDarwin.cpp?rev=<wbr>280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadDarwin.cpp (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadDarwin.cpp Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,324 @@<br>
+//===-- NativeThreadDarwin.cpp ------------------------------<wbr>-- -*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "NativeThreadDarwin.h"<br>
+<br>
+// C includes<br>
+#include <libproc.h><br>
+<br>
+// LLDB includes<br>
+#include "lldb/Core/Stream.h"<br>
+<br>
+#include "NativeProcessDarwin.h"<br>
+<br>
+using namespace lldb;<br>
+using namespace lldb_private;<br>
+using namespace lldb_private::process_darwin;<br>
+<br>
+uint64_t<br>
+NativeThreadDarwin::<wbr>GetGloballyUniqueThreadIDForMa<wbr>chPortID(<br>
+                                                        ::thread_t mach_port_id)<br>
+{<br>
+    thread_identifier_info_data_t tident;<br>
+    mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT;<br>
+<br>
+    auto mach_err = ::thread_info(mach_port_id, THREAD_IDENTIFIER_INFO,<br>
+                                  (thread_info_t) &tident, &tident_count);<br>
+    if (mach_err != KERN_SUCCESS)<br>
+    {<br>
+        // When we fail to get thread info for the supposed port, assume it is<br>
+        // really a globally unique thread id already, or return the best thing<br>
+        // we can, which is the thread port.<br>
+        return mach_port_id;<br>
+    }<br>
+    return tident.thread_id;<br>
+}<br>
+<br>
+NativeThreadDarwin::<wbr>NativeThreadDarwin(<wbr>NativeProcessDarwin *process,<br>
+                                       bool is_64_bit,<br>
+                                       lldb::tid_t unique_thread_id,<br>
+                                       ::thread_t mach_thread_port) :<br>
+    NativeThreadProtocol(process, unique_thread_id),<br>
+    m_mach_thread_port(mach_<wbr>thread_port),<br>
+    m_basic_info(),<br>
+    m_proc_threadinfo()<br>
+{<br>
+}<br>
+<br>
+bool<br>
+NativeThreadDarwin::<wbr>GetIdentifierInfo()<br>
+{<br>
+    // Don't try to get the thread info once and cache it for the life of the thread.  It changes over time, for instance<br>
+    // if the thread name changes, then the thread_handle also changes...  So you have to refetch it every time.<br>
+    mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;<br>
+    kern_return_t kret = ::thread_info(m_mach_thread_<wbr>port,<br>
+                                       THREAD_IDENTIFIER_INFO,<br>
+                                       (thread_info_t) &m_ident_info, &count);<br>
+    return kret == KERN_SUCCESS;<br>
+<br>
+    return false;<br>
+}<br>
+<br>
+std::string<br>
+NativeThreadDarwin::GetName()<br>
+{<br>
+    std::string name;<br>
+<br>
+    if (GetIdentifierInfo())<br>
+    {<br>
+        auto process_sp = GetProcess();<br>
+        if (!process_sp)<br>
+        {<br>
+            name = "<unavailable>";<br>
+            return name;<br>
+        }<br>
+<br>
+        int len = ::proc_pidinfo(process_sp-><wbr>GetID(), PROC_PIDTHREADINFO,<br>
+                                 m_ident_info.thread_handle, &m_proc_threadinfo,<br>
+                                 sizeof(m_proc_threadinfo));<br>
+<br>
+        if (len && m_proc_threadinfo.pth_name[0])<br>
+            name = m_proc_threadinfo.pth_name;<br>
+    }<br>
+    return name;<br>
+}<br>
+<br>
+lldb::StateType<br>
+NativeThreadDarwin::GetState(<wbr>)<br>
+{<br>
+    // TODO implement<br>
+    return eStateInvalid;<br>
+}<br>
+<br>
+bool<br>
+NativeThreadDarwin::<wbr>GetStopReason(ThreadStopInfo &stop_info,<br>
+                                  std::string& description)<br>
+{<br>
+    // TODO implement<br>
+    return false;<br>
+}<br>
+<br>
+NativeRegisterContextSP<br>
+NativeThreadDarwin::<wbr>GetRegisterContext()<br>
+{<br>
+    // TODO implement<br>
+    return NativeRegisterContextSP();<br>
+}<br>
+<br>
+Error<br>
+NativeThreadDarwin::<wbr>SetWatchpoint(lldb::addr_t addr, size_t size,<br>
+                                  uint32_t watch_flags, bool hardware)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("not yet implemented");<br>
+    return error;<br>
+}<br>
+<br>
+Error<br>
+NativeThreadDarwin::<wbr>RemoveWatchpoint(lldb::addr_t addr)<br>
+{<br>
+    Error error;<br>
+    error.SetErrorString("not yet implemented");<br>
+    return error;<br>
+}<br>
+<br>
+void<br>
+NativeThreadDarwin::Dump(<wbr>Stream &stream) const<br>
+{<br>
+    // This is what we really want once we have the thread class wired up.<br>
+#if 0<br>
+    DNBLogThreaded("[%3u] #%3u tid: 0x%8.8" PRIx64 ", pc: 0x%16.16" PRIx64 ", sp: 0x%16.16" PRIx64 ", user: %d.%6.6d, system: %d.%6.6d, cpu: %2d, policy: %2d, run_state: %2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d",<br>
+                   index,<br>
+                   m_seq_id,<br>
+                   m_unique_id,<br>
+                   GetPC(INVALID_NUB_ADDRESS),<br>
+                   GetSP(INVALID_NUB_ADDRESS),<br>
+                   m_basic_info.user_time.<wbr>seconds,      m_basic_info.user_time.<wbr>microseconds,<br>
+                   m_basic_info.system_time.<wbr>seconds,    m_basic_info.system_time.<wbr>microseconds,<br>
+                   m_basic_info.cpu_usage,<br>
+                   m_basic_info.policy,<br>
+                   m_basic_info.run_state,<br>
+                   thread_run_state,<br>
+                   m_basic_info.flags,<br>
+                   m_basic_info.suspend_count, m_suspend_count,<br>
+                   m_basic_info.sleep_time);<br>
+<br>
+#else<br>
+    // Here's all we have right now.<br>
+    stream.Printf("tid: 0x%8.8" PRIx64 ", thread port: 0x%4.4x",<br>
+                  GetID(), m_mach_thread_port);<br>
+#endif<br>
+}<br>
+<br>
+bool<br>
+NativeThreadDarwin::<wbr>NotifyException(MachException:<wbr>:Data &exc)<br>
+{<br>
+    // TODO implement this.<br>
+#if 0<br>
+    // Allow the arch specific protocol to process (MachException::Data &)exc<br>
+    // first before possible reassignment of m_stop_exception with exc.<br>
+    // See also MachThread::GetStopException()<wbr>.<br>
+    bool handled = m_arch_ap->NotifyException(<wbr>exc);<br>
+<br>
+    if (m_stop_exception.IsValid())<br>
+    {<br>
+        // We may have more than one exception for a thread, but we need to<br>
+        // only remember the one that we will say is the reason we stopped.<br>
+        // We may have been single stepping and also gotten a signal exception,<br>
+        // so just remember the most pertinent one.<br>
+        if (m_stop_exception.<wbr>IsBreakpoint())<br>
+            m_stop_exception = exc;<br>
+    }<br>
+    else<br>
+    {<br>
+        m_stop_exception = exc;<br>
+    }<br>
+<br>
+    return handled;<br>
+#else<br>
+    // Pretend we handled it.<br>
+    return true;<br>
+#endif<br>
+}<br>
+<br>
+bool<br>
+NativeThreadDarwin::<wbr>ShouldStop(bool &step_more) const<br>
+{<br>
+    // TODO: implement this<br>
+#if 0<br>
+    // See if this thread is at a breakpoint?<br>
+    DNBBreakpoint *bp = CurrentBreakpoint();<br>
+<br>
+    if (bp)<br>
+    {<br>
+        // This thread is sitting at a breakpoint, ask the breakpoint<br>
+        // if we should be stopping here.<br>
+        return true;<br>
+    }<br>
+    else<br>
+    {<br>
+        if (m_arch_ap->StepNotComplete())<br>
+        {<br>
+            step_more = true;<br>
+            return false;<br>
+        }<br>
+        // The thread state is used to let us know what the thread was<br>
+        // trying to do. MachThread::ThreadWillResume() will set the<br>
+        // thread state to various values depending if the thread was<br>
+        // the current thread and if it was to be single stepped, or<br>
+        // resumed.<br>
+        if (GetState() == eStateRunning)<br>
+        {<br>
+            // If our state is running, then we should continue as we are in<br>
+            // the process of stepping over a breakpoint.<br>
+            return false;<br>
+        }<br>
+        else<br>
+        {<br>
+            // Stop if we have any kind of valid exception for this<br>
+            // thread.<br>
+            if (GetStopException().IsValid())<br>
+                return true;<br>
+        }<br>
+    }<br>
+    return false;<br>
+#else<br>
+    return false;<br>
+#endif<br>
+}<br>
+<br>
+void<br>
+NativeThreadDarwin::<wbr>ThreadDidStop()<br>
+{<br>
+    // TODO implement this.<br>
+#if 0<br>
+    // This thread has existed prior to resuming under debug nub control,<br>
+    // and has just been stopped. Do any cleanup that needs to be done<br>
+    // after running.<br>
+<br>
+    // The thread state and breakpoint will still have the same values<br>
+    // as they had prior to resuming the thread, so it makes it easy to check<br>
+    // if we were trying to step a thread, or we tried to resume while being<br>
+    // at a breakpoint.<br>
+<br>
+    // When this method gets called, the process state is still in the<br>
+    // state it was in while running so we can act accordingly.<br>
+    m_arch_ap->ThreadDidStop();<br>
+<br>
+<br>
+    // We may have suspended this thread so the primary thread could step<br>
+    // without worrying about race conditions, so lets restore our suspend<br>
+    // count.<br>
+    RestoreSuspendCountAfterStop()<wbr>;<br>
+<br>
+    // Update the basic information for a thread<br>
+    MachThread::GetBasicInfo(m_<wbr>mach_port_number, &m_basic_info);<br>
+<br>
+    if (m_basic_info.suspend_count > 0)<br>
+        SetState(eStateSuspended);<br>
+    else<br>
+        SetState(eStateStopped);<br>
+#endif<br>
+}<br>
+<br>
+bool<br>
+NativeThreadDarwin::<wbr>MachPortNumberIsValid(::<wbr>thread_t thread)<br>
+{<br>
+    return thread != (::thread_t)(0);<br>
+}<br>
+<br>
+const struct thread_basic_info *<br>
+NativeThreadDarwin::<wbr>GetBasicInfo() const<br>
+{<br>
+    if (GetBasicInfo(m_mach_thread_<wbr>port, &m_basic_info))<br>
+        return &m_basic_info;<br>
+    return NULL;<br>
+}<br>
+<br>
+bool<br>
+NativeThreadDarwin::<wbr>GetBasicInfo(::thread_t thread,<br>
+                                 struct thread_basic_info *basicInfoPtr)<br>
+{<br>
+    if (MachPortNumberIsValid(thread)<wbr>)<br>
+    {<br>
+        unsigned int info_count = THREAD_BASIC_INFO_COUNT;<br>
+        kern_return_t err = ::thread_info (thread, THREAD_BASIC_INFO, (thread_info_t) basicInfoPtr, &info_count);<br>
+        if (err == KERN_SUCCESS)<br>
+            return true;<br>
+    }<br>
+    ::memset (basicInfoPtr, 0, sizeof (struct thread_basic_info));<br>
+    return false;<br>
+}<br>
+<br>
+bool<br>
+NativeThreadDarwin::<wbr>IsUserReady() const<br>
+{<br>
+    if (m_basic_info.run_state == 0)<br>
+        GetBasicInfo();<br>
+<br>
+    switch (m_basic_info.run_state)<br>
+    {<br>
+        default:<br>
+        case TH_STATE_UNINTERRUPTIBLE:<br>
+            break;<br>
+<br>
+        case TH_STATE_RUNNING:<br>
+        case TH_STATE_STOPPED:<br>
+        case TH_STATE_WAITING:<br>
+        case TH_STATE_HALTED:<br>
+            return true;<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+NativeProcessDarwinSP<br>
+NativeThreadDarwin::<wbr>GetNativeProcessDarwinSP()<br>
+{<br>
+    return std::static_pointer_cast<<wbr>NativeProcessDarwin>(<wbr>GetProcess());<br>
+}<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadDarwin.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/NativeThreadDarwin.h?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>NativeThreadDarwin.h?rev=<wbr>280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadDarwin.h (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadDarwin.h Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,216 @@<br>
+//===-- NativeThreadDarwin.h ------------------------------<wbr>---- -*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef NativeThreadDarwin_H<br>
+#define NativeThreadDarwin_H<br>
+<br>
+// C includes<br>
+#include <mach/mach_types.h><br>
+#include <sched.h><br>
+#include <sys/proc_info.h><br>
+<br>
+// C++ includes<br>
+#include <map><br>
+#include <memory><br>
+#include <string><br>
+<br>
+// LLDB includes<br>
+#include "lldb/lldb-private-forward.h"<br>
+#include "lldb/Host/common/<wbr>NativeThreadProtocol.h"<br>
+<br>
+#include "MachException.h"<br>
+<br>
+namespace lldb_private {<br>
+namespace process_darwin {<br>
+<br>
+class NativeProcessDarwin;<br>
+using NativeProcessDarwinSP = std::shared_ptr<<wbr>NativeProcessDarwin>;<br>
+<br>
+class NativeThreadListDarwin;<br>
+<br>
+class NativeThreadDarwin : public NativeThreadProtocol<br>
+{<br>
+    friend class NativeProcessDarwin;<br>
+    friend class NativeThreadListDarwin;<br>
+<br>
+public:<br>
+<br>
+    static uint64_t<br>
+    GetGloballyUniqueThreadIDForMa<wbr>chPortID(::thread_t mach_port_id);<br>
+<br>
+    NativeThreadDarwin(<wbr>NativeProcessDarwin *process, bool is_64_bit,<br>
+                       lldb::tid_t unique_thread_id = 0,<br>
+                       ::thread_t mach_thread_port = 0);<br>
+<br>
+    // ------------------------------<wbr>------------------------------<wbr>-----<br>
+    // NativeThreadProtocol Interface<br>
+    // ------------------------------<wbr>------------------------------<wbr>-----<br>
+    std::string<br>
+    GetName() override;<br>
+<br>
+    lldb::StateType<br>
+    GetState () override;<br>
+<br>
+    bool<br>
+    GetStopReason(ThreadStopInfo &stop_info,<br>
+                  std::string& description) override;<br>
+<br>
+    NativeRegisterContextSP<br>
+    GetRegisterContext() override;<br>
+<br>
+    Error<br>
+    SetWatchpoint(lldb::addr_t addr, size_t size,<br>
+                  uint32_t watch_flags, bool hardware) override;<br>
+<br>
+    Error<br>
+    RemoveWatchpoint(lldb::addr_t addr) override;<br>
+<br>
+    // ------------------------------<wbr>------------------------------<wbr>-----<br>
+    // New methods that are fine for others to call.<br>
+    // ------------------------------<wbr>------------------------------<wbr>-----<br>
+    void<br>
+    Dump(Stream &stream) const;<br>
+<br>
+private:<br>
+    // ------------------------------<wbr>------------------------------<wbr>-----<br>
+    // Interface for friend classes<br>
+    // ------------------------------<wbr>------------------------------<wbr>-----<br>
+<br>
+    /// Resumes the thread.  If @p signo is anything but<br>
+    /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.<br>
+    Error<br>
+    Resume(uint32_t signo);<br>
+<br>
+    /// Single steps the thread.  If @p signo is anything but<br>
+    /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.<br>
+    Error<br>
+    SingleStep(uint32_t signo);<br>
+<br>
+    bool<br>
+    NotifyException(MachException:<wbr>:Data &exc);<br>
+<br>
+    bool<br>
+    ShouldStop(bool &step_more) const;<br>
+<br>
+    void<br>
+    ThreadDidStop();<br>
+<br>
+    void<br>
+    SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);<br>
+<br>
+    /// Return true if the thread is stopped.<br>
+    /// If stopped by a signal, indicate the signo in the signo<br>
+    /// argument.  Otherwise, return LLDB_INVALID_SIGNAL_NUMBER.<br>
+    bool<br>
+    IsStopped (int *signo);<br>
+<br>
+    const struct thread_basic_info *<br>
+    GetBasicInfo() const;<br>
+<br>
+    static bool<br>
+    GetBasicInfo(::thread_t thread, struct thread_basic_info *basicInfoPtr);<br>
+<br>
+    bool<br>
+    IsUserReady() const;<br>
+<br>
+    void<br>
+    SetStoppedByExec ();<br>
+<br>
+    void<br>
+    SetStoppedByBreakpoint ();<br>
+<br>
+    void<br>
+    SetStoppedByWatchpoint (uint32_t wp_index);<br>
+<br>
+    bool<br>
+    IsStoppedAtBreakpoint ();<br>
+<br>
+    bool<br>
+    IsStoppedAtWatchpoint ();<br>
+<br>
+    void<br>
+    SetStoppedByTrace ();<br>
+<br>
+    void<br>
+    SetStoppedWithNoReason ();<br>
+<br>
+    void<br>
+    SetExited ();<br>
+<br>
+    Error<br>
+    RequestStop ();<br>
+<br>
+    // ------------------------------<wbr>------------------------------<wbr>-------------<br>
+    /// Return the mach thread port number for this thread.<br>
+    ///<br>
+    /// @return<br>
+    ///     The mach port number for this thread.  Returns NULL_THREAD<br>
+    ///     when the thread is invalid.<br>
+    // ------------------------------<wbr>------------------------------<wbr>-------------<br>
+    thread_t<br>
+    GetMachPortNumber() const<br>
+    {<br>
+        return m_mach_thread_port;<br>
+    }<br>
+<br>
+    static bool<br>
+    MachPortNumberIsValid(::<wbr>thread_t thread);<br>
+<br>
+    // ------------------------------<wbr>------------------------------<wbr>---------<br>
+    // Private interface<br>
+    // ------------------------------<wbr>------------------------------<wbr>---------<br>
+    bool<br>
+    GetIdentifierInfo();<br>
+<br>
+    void<br>
+    MaybeLogStateChange (lldb::StateType new_state);<br>
+<br>
+    NativeProcessDarwinSP<br>
+    GetNativeProcessDarwinSP();<br>
+<br>
+    void<br>
+    SetStopped();<br>
+<br>
+    inline void<br>
+    MaybePrepareSingleStepWorkarou<wbr>nd();<br>
+<br>
+    inline void<br>
+    MaybeCleanupSingleStepWorkarou<wbr>nd();<br>
+<br>
+    // ------------------------------<wbr>------------------------------<wbr>-----<br>
+    // Member Variables<br>
+    // ------------------------------<wbr>------------------------------<wbr>-----<br>
+<br>
+    // The mach thread port for the thread.<br>
+    ::thread_t  m_mach_thread_port;<br>
+<br>
+    // The most recently-retrieved thread basic info.<br>
+    mutable ::thread_basic_info m_basic_info;<br>
+<br>
+    struct proc_threadinfo  m_proc_threadinfo;<br>
+<br>
+    thread_identifier_info_data_t   m_ident_info;<br>
+<br>
+#if 0<br>
+    lldb::StateType m_state;<br>
+    ThreadStopInfo m_stop_info;<br>
+    NativeRegisterContextSP m_reg_context_sp;<br>
+    std::string m_stop_description;<br>
+    using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>;<br>
+    WatchpointIndexMap m_watchpoint_index_map;<br>
+    // cpu_set_t m_original_cpu_set; // For single-step workaround.<br>
+#endif<br>
+};<br>
+<br>
+typedef std::shared_ptr<<wbr>NativeThreadDarwin> NativeThreadDarwinSP;<br>
+<br>
+} // namespace process_darwin<br>
+} // namespace lldb_private<br>
+<br>
+#endif // #ifndef NativeThreadDarwin_H<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadListDarwin.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>NativeThreadListDarwin.cpp?<wbr>rev=280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadListDarwin.cpp (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadListDarwin.cpp Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,745 @@<br>
+//===-- NativeThreadListDarwin.cpp ------------------------------<wbr>------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//  Created by Greg Clayton on 6/19/07.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#include "NativeThreadListDarwin.h"<br>
+<br>
+// C includes<br>
+#include <inttypes.h><br>
+#include <mach/vm_map.h><br>
+#include <sys/sysctl.h><br>
+<br>
+// LLDB includes<br>
+#include "lldb/Core/Error.h"<br>
+#include "lldb/Core/Log.h"<br>
+#include "lldb/Core/Stream.h"<br>
+#include "lldb/lldb-enumerations.h"<br>
+<br>
+#include "NativeProcessDarwin.h"<br>
+#include "NativeThreadDarwin.h"<br>
+<br>
+using namespace lldb;<br>
+using namespace lldb_private;<br>
+using namespace lldb_private::process_darwin;<br>
+<br>
+NativeThreadListDarwin::<wbr>NativeThreadListDarwin() :<br>
+    m_threads(),<br>
+    m_threads_mutex(),<br>
+    m_is_64_bit(false)<br>
+{<br>
+}<br>
+<br>
+NativeThreadListDarwin::~<wbr>NativeThreadListDarwin()<br>
+{<br>
+}<br>
+<br>
+// These methods will be accessed directly from NativeThreadDarwin<br>
+#if 0<br>
+nub_state_t<br>
+NativeThreadListDarwin::<wbr>GetState(nub_thread_t tid)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->GetState();<br>
+    return eStateInvalid;<br>
+}<br>
+<br>
+const char *<br>
+NativeThreadListDarwin::<wbr>GetName (nub_thread_t tid)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->GetName();<br>
+    return NULL;<br>
+}<br>
+#endif<br>
+<br>
+// TODO: figure out if we need to add this to NativeThreadDarwin yet.<br>
+#if 0<br>
+ThreadInfo::QoS<br>
+NativeThreadListDarwin::<wbr>GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->GetRequestedQoS(<wbr>tsd, dti_qos_class_index);<br>
+    return ThreadInfo::QoS();<br>
+}<br>
+<br>
+nub_addr_t<br>
+NativeThreadListDarwin::<wbr>GetPThreadT (nub_thread_t tid)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->GetPThreadT();<br>
+    return INVALID_NUB_ADDRESS;<br>
+}<br>
+<br>
+nub_addr_t<br>
+NativeThreadListDarwin::<wbr>GetDispatchQueueT (nub_thread_t tid)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->GetDispatchQueueT()<wbr>;<br>
+    return INVALID_NUB_ADDRESS;<br>
+}<br>
+<br>
+nub_addr_t<br>
+NativeThreadListDarwin::<wbr>GetTSDAddressForThread (nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_<wbr>offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp-><wbr>GetTSDAddressForThread(plo_<wbr>pthread_tsd_base_address_<wbr>offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);<br>
+    return INVALID_NUB_ADDRESS;<br>
+}<br>
+#endif<br>
+<br>
+// TODO implement these<br>
+#if 0<br>
+nub_thread_t<br>
+NativeThreadListDarwin::<wbr>SetCurrentThread(nub_thread_t tid)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+    {<br>
+        m_current_thread = thread_sp;<br>
+        return tid;<br>
+    }<br>
+    return INVALID_NUB_THREAD;<br>
+}<br>
+<br>
+<br>
+bool<br>
+NativeThreadListDarwin::<wbr>GetThreadStoppedReason(nub_<wbr>thread_t tid, struct DNBThreadStopInfo *stop_info) const<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->GetStopException().<wbr>GetStopInfo(stop_info);<br>
+    return false;<br>
+}<br>
+<br>
+bool<br>
+NativeThreadListDarwin::<wbr>GetIdentifierInfo (nub_thread_t tid, thread_identifier_info_data_t *ident_info)<br>
+{<br>
+    thread_t mach_port_number = GetMachPortNumberByThreadID (tid);<br>
+<br>
+    mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;<br>
+    return ::thread_info (mach_port_number, THREAD_IDENTIFIER_INFO, (thread_info_t)ident_info, &count) == KERN_SUCCESS;<br>
+}<br>
+<br>
+void<br>
+NativeThreadListDarwin::<wbr>DumpThreadStoppedReason (nub_thread_t tid) const<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        thread_sp->GetStopException().<wbr>DumpStopReason();<br>
+}<br>
+<br>
+const char *<br>
+NativeThreadListDarwin::<wbr>GetThreadInfo (nub_thread_t tid) const<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp-><wbr>GetBasicInfoAsString();<br>
+    return NULL;<br>
+}<br>
+<br>
+#endif<br>
+<br>
+NativeThreadDarwinSP<br>
+NativeThreadListDarwin::<wbr>GetThreadByID(lldb::tid_t tid) const<br>
+{<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_threads_mutex);<br>
+    for (auto thread_sp : m_threads)<br>
+    {<br>
+        if (thread_sp && (thread_sp->GetID() == tid))<br>
+            return thread_sp;<br>
+    }<br>
+    return NativeThreadDarwinSP();<br>
+}<br>
+<br>
+NativeThreadDarwinSP<br>
+NativeThreadListDarwin::<wbr>GetThreadByMachPortNumber(::<wbr>thread_t mach_port_number)<br>
+    const<br>
+{<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_threads_mutex);<br>
+    for (auto thread_sp : m_threads)<br>
+    {<br>
+        if (thread_sp && (thread_sp->GetMachPortNumber(<wbr>) == mach_port_number))<br>
+            return thread_sp;<br>
+    }<br>
+    return NativeThreadDarwinSP();<br>
+}<br>
+<br>
+lldb::tid_t<br>
+NativeThreadListDarwin::<wbr>GetThreadIDByMachPortNumber(::<wbr>thread_t mach_port_number)<br>
+    const<br>
+{<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_threads_mutex);<br>
+    for (auto thread_sp : m_threads)<br>
+    {<br>
+        if (thread_sp && (thread_sp->GetMachPortNumber(<wbr>) == mach_port_number))<br>
+            return thread_sp->GetID();<br>
+    }<br>
+    return LLDB_INVALID_THREAD_ID;<br>
+}<br>
+<br>
+// TODO implement<br>
+#if 0<br>
+thread_t<br>
+NativeThreadListDarwin::<wbr>GetMachPortNumberByThreadID (nub_thread_t globally_unique_id) const<br>
+{<br>
+    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);<br>
+    MachThreadSP thread_sp;<br>
+    const size_t num_threads = m_threads.size();<br>
+    for (size_t idx = 0; idx < num_threads; ++idx)<br>
+    {<br>
+        if (m_threads[idx]->ThreadID() == globally_unique_id)<br>
+        {<br>
+            return m_threads[idx]-><wbr>MachPortNumber();<br>
+        }<br>
+    }<br>
+    return 0;<br>
+}<br>
+<br>
+bool<br>
+NativeThreadListDarwin::<wbr>GetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value ) const<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->GetRegisterValue(<wbr>set, reg, reg_value);<br>
+<br>
+    return false;<br>
+}<br>
+<br>
+bool<br>
+NativeThreadListDarwin::<wbr>SetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *reg_value ) const<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->SetRegisterValue(<wbr>set, reg, reg_value);<br>
+<br>
+    return false;<br>
+}<br>
+<br>
+nub_size_t<br>
+NativeThreadListDarwin::<wbr>GetRegisterContext (nub_thread_t tid, void *buf, size_t buf_len)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->GetRegisterContext (buf, buf_len);<br>
+    return 0;<br>
+}<br>
+<br>
+nub_size_t<br>
+NativeThreadListDarwin::<wbr>SetRegisterContext (nub_thread_t tid, const void *buf, size_t buf_len)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->SetRegisterContext (buf, buf_len);<br>
+    return 0;<br>
+}<br>
+<br>
+uint32_t<br>
+NativeThreadListDarwin::<wbr>SaveRegisterState (nub_thread_t tid)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp->SaveRegisterState ();<br>
+    return 0;<br>
+}<br>
+<br>
+bool<br>
+NativeThreadListDarwin::<wbr>RestoreRegisterState (nub_thread_t tid, uint32_t save_id)<br>
+{<br>
+    MachThreadSP thread_sp (GetThreadByID (tid));<br>
+    if (thread_sp)<br>
+        return thread_sp-><wbr>RestoreRegisterState (save_id);<br>
+    return 0;<br>
+}<br>
+#endif<br>
+<br>
+size_t<br>
+NativeThreadListDarwin::<wbr>GetNumberOfThreads() const<br>
+{<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_threads_mutex);<br>
+    return static_cast<size_t>(m_threads.<wbr>size());<br>
+}<br>
+<br>
+// TODO implement<br>
+#if 0<br>
+nub_thread_t<br>
+NativeThreadListDarwin::<wbr>ThreadIDAtIndex (nub_size_t idx) const<br>
+{<br>
+    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);<br>
+    if (idx < m_threads.size())<br>
+        return m_threads[idx]->ThreadID();<br>
+    return INVALID_NUB_THREAD;<br>
+}<br>
+<br>
+nub_thread_t<br>
+NativeThreadListDarwin::<wbr>CurrentThreadID ( )<br>
+{<br>
+    MachThreadSP thread_sp;<br>
+    CurrentThread(thread_sp);<br>
+    if (thread_sp.get())<br>
+        return thread_sp->ThreadID();<br>
+    return INVALID_NUB_THREAD;<br>
+}<br>
+<br>
+#endif<br>
+<br>
+bool<br>
+NativeThreadListDarwin::<wbr>NotifyException(MachException:<wbr>:Data &exc)<br>
+{<br>
+    auto thread_sp = GetThreadByMachPortNumber(exc.<wbr>thread_port);<br>
+    if (thread_sp)<br>
+    {<br>
+        thread_sp->NotifyException(<wbr>exc);<br>
+        return true;<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+void<br>
+NativeThreadListDarwin::<wbr>Clear()<br>
+{<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_threads_mutex);<br>
+    m_threads.clear();<br>
+}<br>
+<br>
+uint32_t<br>
+NativeThreadListDarwin::<wbr>UpdateThreadList(<wbr>NativeProcessDarwin &process,<br>
+                                         bool update,<br>
+                                         collection *new_threads)<br>
+{<br>
+    Log *log(GetLogIfAllCategoriesSet(<wbr>LIBLLDB_LOG_THREAD));<br>
+<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_threads_mutex);<br>
+    if (log)<br>
+        log->Printf("<wbr>NativeThreadListDarwin::%s() (pid = %" PRIu64 ", update = "<br>
+                    "%u) process stop count = %u", __FUNCTION__,<br>
+                    process.GetID(), update, process.GetStopID());<br>
+<br>
+    if (process.GetStopID() == 0)<br>
+    {<br>
+        // On our first stop, we'll record details like 32/64 bitness and<br>
+        // select the proper architecture implementation.<br>
+        //<br>
+        int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID,<br>
+            (int)process.GetID() };<br>
+<br>
+        struct kinfo_proc processInfo;<br>
+        size_t bufsize = sizeof(processInfo);<br>
+        if ((sysctl(mib, (unsigned)(sizeof(mib)/sizeof(<wbr>int)), &processInfo,<br>
+                    &bufsize, NULL, 0) == 0) && (bufsize > 0))<br>
+        {<br>
+            if (processInfo.kp_proc.p_flag & P_LP64)<br>
+                m_is_64_bit = true;<br>
+        }<br>
+<br>
+// TODO implement architecture selection and abstraction.<br>
+#if 0<br>
+#if defined (__i386__) || defined (__x86_64__)<br>
+        if (m_is_64_bit)<br>
+            DNBArchProtocol::<wbr>SetArchitecture(CPU_TYPE_X86_<wbr>64);<br>
+        else<br>
+            DNBArchProtocol::<wbr>SetArchitecture(CPU_TYPE_I386)<wbr>;<br>
+#elif defined (__arm__) || defined (__arm64__) || defined (__aarch64__)<br>
+        if (m_is_64_bit)<br>
+            DNBArchProtocol::<wbr>SetArchitecture(CPU_TYPE_<wbr>ARM64);<br>
+        else<br>
+            DNBArchProtocol::<wbr>SetArchitecture(CPU_TYPE_ARM);<br>
+#endif<br>
+#endif<br>
+    }<br>
+<br>
+    if (m_threads.empty() || update)<br>
+    {<br>
+        thread_array_t thread_list = nullptr;<br>
+        mach_msg_type_number_t thread_list_count = 0;<br>
+        task_t task = process.GetTask();<br>
+<br>
+        Error error;<br>
+        auto mach_err = ::task_threads(task, &thread_list, &thread_list_count);<br>
+        error.SetError(mach_err, eErrorTypeMachKernel);<br>
+        if (error.Fail())<br>
+        {<br>
+            if (log)<br>
+                log->Printf("::task_threads(<wbr>task = 0x%4.4x, thread_list => %p, "<br>
+                            "thread_list_count => %u) failed: %u (%s)", task,<br>
+                            thread_list, thread_list_count, error.GetError(),<br>
+                            error.AsCString());<br>
+            return 0;<br>
+        }<br>
+<br>
+        if (thread_list_count > 0)<br>
+        {<br>
+            collection currThreads;<br>
+            size_t idx;<br>
+            // Iterator through the current thread list and see which threads<br>
+            // we already have in our list (keep them), which ones we don't<br>
+            // (add them), and which ones are not around anymore (remove them).<br>
+            for (idx = 0; idx < thread_list_count; ++idx)<br>
+            {<br>
+                // Get the Mach thread port.<br>
+                const ::thread_t mach_port_num = thread_list[idx];<br>
+<br>
+                // Get the unique thread id for the mach port number.<br>
+                uint64_t unique_thread_id =<br>
+                    NativeThreadDarwin::<br>
+                    GetGloballyUniqueThreadIDForMa<wbr>chPortID(mach_port_num);<br>
+<br>
+                // Retrieve the thread if it exists.<br>
+                auto thread_sp = GetThreadByID(unique_thread_<wbr>id);<br>
+                if (thread_sp)<br>
+                {<br>
+                    // We are already tracking it. Keep the existing native<br>
+                    // thread instance.<br>
+                    currThreads.push_back(thread_<wbr>sp);<br>
+                }<br>
+                else<br>
+                {<br>
+                    // We don't have a native thread instance for this thread.<br>
+                    // Create it now.<br>
+                    thread_sp.reset(new NativeThreadDarwin(&process,<br>
+                                                           m_is_64_bit,<br>
+                                                           unique_thread_id,<br>
+                                                           mach_port_num));<br>
+<br>
+                    // Add the new thread regardless of its is user ready state.<br>
+                    // Make sure the thread is ready to be displayed and shown<br>
+                    // to users before we add this thread to our list...<br>
+                    if (thread_sp->IsUserReady())<br>
+                    {<br>
+                        if (new_threads)<br>
+                            new_threads->push_back(thread_<wbr>sp);<br>
+<br>
+                        currThreads.push_back(thread_<wbr>sp);<br>
+                    }<br>
+                }<br>
+            }<br>
+<br>
+            m_threads.swap(currThreads);<br>
+            m_current_thread.reset();<br>
+<br>
+            // Free the vm memory given to us by ::task_threads()<br>
+            vm_size_t thread_list_size = (vm_size_t) (thread_list_count *<br>
+                                                      sizeof (::thread_t));<br>
+            ::vm_deallocate(::mach_task_<wbr>self(),<br>
+                            (vm_address_t)thread_list,<br>
+                            thread_list_size);<br>
+        }<br>
+    }<br>
+    return static_cast<uint32_t>(m_<wbr>threads.size());<br>
+}<br>
+<br>
+// TODO implement<br>
+#if 0<br>
+<br>
+void<br>
+NativeThreadListDarwin::<wbr>CurrentThread (MachThreadSP& thread_sp)<br>
+{<br>
+    // locker will keep a mutex locked until it goes out of scope<br>
+    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);<br>
+    if (m_current_thread.get() == NULL)<br>
+    {<br>
+        // Figure out which thread is going to be our current thread.<br>
+        // This is currently done by finding the first thread in the list<br>
+        // that has a valid exception.<br>
+        const size_t num_threads = m_threads.size();<br>
+        for (uint32_t idx = 0; idx < num_threads; ++idx)<br>
+        {<br>
+            if (m_threads[idx]-><wbr>GetStopException().IsValid())<br>
+            {<br>
+                m_current_thread = m_threads[idx];<br>
+                break;<br>
+            }<br>
+        }<br>
+    }<br>
+    thread_sp = m_current_thread;<br>
+}<br>
+<br>
+#endif<br>
+<br>
+void<br>
+NativeThreadListDarwin::Dump(<wbr>Stream &stream) const<br>
+{<br>
+    bool first = true;<br>
+<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_threads_mutex);<br>
+    for (auto thread_sp : m_threads)<br>
+    {<br>
+        if (thread_sp)<br>
+        {<br>
+            // Handle newlines between thread entries.<br>
+            if (first)<br>
+                first = false;<br>
+            else<br>
+                stream.PutChar('\n');<br>
+            thread_sp->Dump(stream);<br>
+        }<br>
+    }<br>
+}<br>
+<br>
+void<br>
+NativeThreadListDarwin::<wbr>ProcessWillResume(<wbr>NativeProcessDarwin &process,<br>
+                                    const ResumeActionList &thread_actions)<br>
+{<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_threads_mutex);<br>
+<br>
+    // Update our thread list, because sometimes libdispatch or the kernel<br>
+    // will spawn threads while a task is suspended.<br>
+    NativeThreadListDarwin::<wbr>collection new_threads;<br>
+<br>
+    // TODO implement this.<br>
+#if 0<br>
+    // First figure out if we were planning on running only one thread, and if<br>
+    // so, force that thread to resume.<br>
+    bool run_one_thread;<br>
+    thread_t solo_thread = THREAD_NULL;<br>
+    if ((thread_actions.GetSize() > 0) &&<br>
+        (thread_actions.<wbr>NumActionsWithState(<wbr>eStateStepping) +<br>
+         thread_actions.<wbr>NumActionsWithState (eStateRunning) == 1))<br>
+    {<br>
+        run_one_thread = true;<br>
+        const DNBThreadResumeAction *action_ptr = thread_actions.GetFirst();<br>
+        size_t num_actions = thread_actions.GetSize();<br>
+        for (size_t i = 0; i < num_actions; i++, action_ptr++)<br>
+        {<br>
+            if (action_ptr->state == eStateStepping || action_ptr->state == eStateRunning)<br>
+            {<br>
+                solo_thread = action_ptr->tid;<br>
+                break;<br>
+            }<br>
+        }<br>
+    }<br>
+    else<br>
+        run_one_thread = false;<br>
+#endif<br>
+<br>
+    UpdateThreadList(process, true, &new_threads);<br>
+<br>
+#if 0<br>
+    DNBThreadResumeAction resume_new_threads = { -1U, eStateRunning, 0, INVALID_NUB_ADDRESS };<br>
+    // If we are planning to run only one thread, any new threads should be suspended.<br>
+    if (run_one_thread)<br>
+        resume_new_threads.state = eStateSuspended;<br>
+<br>
+    const size_t num_new_threads = new_threads.size();<br>
+    const size_t num_threads = m_threads.size();<br>
+    for (uint32_t idx = 0; idx < num_threads; ++idx)<br>
+    {<br>
+        MachThread *thread = m_threads[idx].get();<br>
+        bool handled = false;<br>
+        for (uint32_t new_idx = 0; new_idx < num_new_threads; ++new_idx)<br>
+        {<br>
+            if (thread == new_threads[new_idx].get())<br>
+            {<br>
+                thread->ThreadWillResume(&<wbr>resume_new_threads);<br>
+                handled = true;<br>
+                break;<br>
+            }<br>
+        }<br>
+<br>
+        if (!handled)<br>
+        {<br>
+            const DNBThreadResumeAction *thread_action = thread_actions.<wbr>GetActionForThread (thread->ThreadID(), true);<br>
+            // There must always be a thread action for every thread.<br>
+            assert (thread_action);<br>
+            bool others_stopped = false;<br>
+            if (solo_thread == thread->ThreadID())<br>
+                others_stopped = true;<br>
+            thread->ThreadWillResume (thread_action, others_stopped);<br>
+        }<br>
+    }<br>
+<br>
+    if (new_threads.size())<br>
+    {<br>
+        for (uint32_t idx = 0; idx < num_new_threads; ++idx)<br>
+        {<br>
+            DNBLogThreadedIf (LOG_THREAD, "NativeThreadListDarwin::<wbr>ProcessWillResume (pid = %4.4x) stop-id=%u, resuming newly discovered thread: 0x%8.8" PRIx64 ", thread-is-user-ready=%i)",<br>
+                              process->ProcessID(),<br>
+                              process->StopCount(),<br>
+                              new_threads[idx]->ThreadID(),<br>
+                              new_threads[idx]->IsUserReady(<wbr>));<br>
+        }<br>
+    }<br>
+#endif<br>
+}<br>
+<br>
+uint32_t<br>
+NativeThreadListDarwin::<wbr>ProcessDidStop(<wbr>NativeProcessDarwin &process)<br>
+{<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_threads_mutex);<br>
+<br>
+    // Update our thread list.<br>
+    UpdateThreadList(process, true);<br>
+<br>
+    for (auto thread_sp : m_threads)<br>
+    {<br>
+        if (thread_sp)<br>
+            thread_sp->ThreadDidStop();<br>
+    }<br>
+    return (uint32_t)m_threads.size();<br>
+}<br>
+<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+// Check each thread in our thread list to see if we should notify our<br>
+// client of the current halt in execution.<br>
+//<br>
+// Breakpoints can have callback functions associated with them than<br>
+// can return true to stop, or false to continue executing the inferior.<br>
+//<br>
+// RETURNS<br>
+//    true if we should stop and notify our clients<br>
+//    false if we should resume our child process and skip notification<br>
+//---------------------------<wbr>------------------------------<wbr>-------------<br>
+bool<br>
+NativeThreadListDarwin::<wbr>ShouldStop(bool &step_more)<br>
+{<br>
+    std::lock_guard<std::<wbr>recursive_mutex> locker(m_threads_mutex);<br>
+    for (auto thread_sp : m_threads)<br>
+    {<br>
+        if (thread_sp && thread_sp->ShouldStop(step_<wbr>more))<br>
+            return true;<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+// Implement.<br>
+#if 0<br>
+<br>
+void<br>
+NativeThreadListDarwin::<wbr>NotifyBreakpointChanged (const DNBBreakpoint *bp)<br>
+{<br>
+    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);<br>
+    const size_t num_threads = m_threads.size();<br>
+    for (uint32_t idx = 0; idx < num_threads; ++idx)<br>
+    {<br>
+        m_threads[idx]-><wbr>NotifyBreakpointChanged(bp);<br>
+    }<br>
+}<br>
+<br>
+<br>
+uint32_t<br>
+NativeThreadListDarwin::<wbr>EnableHardwareBreakpoint (const DNBBreakpoint* bp) const<br>
+{<br>
+    if (bp != NULL)<br>
+    {<br>
+        const size_t num_threads = m_threads.size();<br>
+        for (uint32_t idx = 0; idx < num_threads; ++idx)<br>
+            m_threads[idx]-><wbr>EnableHardwareBreakpoint(bp);<br>
+    }<br>
+    return INVALID_NUB_HW_INDEX;<br>
+}<br>
+<br>
+bool<br>
+NativeThreadListDarwin::<wbr>DisableHardwareBreakpoint (const DNBBreakpoint* bp) const<br>
+{<br>
+    if (bp != NULL)<br>
+    {<br>
+        const size_t num_threads = m_threads.size();<br>
+        for (uint32_t idx = 0; idx < num_threads; ++idx)<br>
+            m_threads[idx]-><wbr>DisableHardwareBreakpoint(bp);<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+// DNBWatchpointSet() -> MachProcess::CreateWatchpoint(<wbr>) -> MachProcess::EnableWatchpoint(<wbr>)<br>
+// -> NativeThreadListDarwin::<wbr>EnableHardwareWatchpoint().<br>
+uint32_t<br>
+NativeThreadListDarwin::<wbr>EnableHardwareWatchpoint (const DNBBreakpoint* wp) const<br>
+{<br>
+    uint32_t hw_index = INVALID_NUB_HW_INDEX;<br>
+    if (wp != NULL)<br>
+    {<br>
+        PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);<br>
+        const size_t num_threads = m_threads.size();<br>
+        // On Mac OS X we have to prime the control registers for new threads.  We do this<br>
+        // using the control register data for the first thread, for lack of a better way of choosing.<br>
+        bool also_set_on_task = true;<br>
+        for (uint32_t idx = 0; idx < num_threads; ++idx)<br>
+        {<br>
+            if ((hw_index = m_threads[idx]-><wbr>EnableHardwareWatchpoint(wp, also_set_on_task)) == INVALID_NUB_HW_INDEX)<br>
+            {<br>
+                // We know that idx failed for some reason.  Let's rollback the transaction for [0, idx).<br>
+                for (uint32_t i = 0; i < idx; ++i)<br>
+                    m_threads[i]-><wbr>RollbackTransForHWP();<br>
+                return INVALID_NUB_HW_INDEX;<br>
+            }<br>
+            also_set_on_task = false;<br>
+        }<br>
+        // Notify each thread to commit the pending transaction.<br>
+        for (uint32_t idx = 0; idx < num_threads; ++idx)<br>
+            m_threads[idx]-><wbr>FinishTransForHWP();<br>
+<br>
+    }<br>
+    return hw_index;<br>
+}<br>
+<br>
+bool<br>
+NativeThreadListDarwin::<wbr>DisableHardwareWatchpoint (const DNBBreakpoint* wp) const<br>
+{<br>
+    if (wp != NULL)<br>
+    {<br>
+        PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);<br>
+        const size_t num_threads = m_threads.size();<br>
+<br>
+        // On Mac OS X we have to prime the control registers for new threads.  We do this<br>
+        // using the control register data for the first thread, for lack of a better way of choosing.<br>
+        bool also_set_on_task = true;<br>
+        for (uint32_t idx = 0; idx < num_threads; ++idx)<br>
+        {<br>
+            if (!m_threads[idx]-><wbr>DisableHardwareWatchpoint(wp, also_set_on_task))<br>
+            {<br>
+                // We know that idx failed for some reason.  Let's rollback the transaction for [0, idx).<br>
+                for (uint32_t i = 0; i < idx; ++i)<br>
+                    m_threads[i]-><wbr>RollbackTransForHWP();<br>
+                return false;<br>
+            }<br>
+            also_set_on_task = false;<br>
+        }<br>
+        // Notify each thread to commit the pending transaction.<br>
+        for (uint32_t idx = 0; idx < num_threads; ++idx)<br>
+            m_threads[idx]-><wbr>FinishTransForHWP();<br>
+<br>
+        return true;<br>
+    }<br>
+    return false;<br>
+}<br>
+<br>
+uint32_t<br>
+NativeThreadListDarwin::<wbr>NumSupportedHardwareWatchpoint<wbr>s () const<br>
+{<br>
+    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);<br>
+    const size_t num_threads = m_threads.size();<br>
+    // Use an arbitrary thread to retrieve the number of supported hardware watchpoints.<br>
+    if (num_threads)<br>
+        return m_threads[0]-><wbr>NumSupportedHardwareWatchpoint<wbr>s();<br>
+    return 0;<br>
+}<br>
+<br>
+uint32_t<br>
+NativeThreadListDarwin::<wbr>GetThreadIndexForThreadStopped<wbr>WithSignal (const int signo) const<br>
+{<br>
+    PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);<br>
+    uint32_t should_stop = false;<br>
+    const size_t num_threads = m_threads.size();<br>
+    for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx)<br>
+    {<br>
+        if (m_threads[idx]-><wbr>GetStopException().SoftSignal () == signo)<br>
+            return idx;<br>
+    }<br>
+    return UINT32_MAX;<br>
+}<br>
+<br>
+#endif<br>
<br>
Added: lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadListDarwin.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Darwin/NativeThreadListDarwin.h?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Darwin/<wbr>NativeThreadListDarwin.h?rev=<wbr>280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadListDarwin.h (added)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Darwin/<wbr>NativeThreadListDarwin.h Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,162 @@<br>
+//===-- NativeThreadListDarwin.h ------------------------------<wbr>--------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+//<br>
+//  Created by Greg Clayton on 6/19/07.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef __NativeThreadListDarwin_h__<br>
+#define __NativeThreadListDarwin_h__<br>
+<br>
+#include <memory><br>
+#include <mutex><br>
+#include <vector><br>
+<br>
+#include "lldb/lldb-private-forward.h"<br>
+#include "lldb/lldb-types.h"<br>
+<br>
+#include "MachException.h"<br>
+<br>
+// #include "ThreadInfo.h"<br>
+<br>
+namespace lldb_private {<br>
+namespace process_darwin {<br>
+<br>
+class NativeBreakpointDarwin;<br>
+class NativeProcessDarwin;<br>
+<br>
+class NativeThreadDarwin;<br>
+using NativeThreadDarwinSP = std::shared_ptr<<wbr>NativeThreadDarwin>;<br>
+<br>
+class NativeThreadListDarwin<br>
+{<br>
+public:<br>
+    NativeThreadListDarwin();<br>
+    ~NativeThreadListDarwin();<br>
+<br>
+    void<br>
+    Clear();<br>
+<br>
+    void<br>
+    Dump(Stream &stream) const;<br>
+<br>
+    // These methods will be accessed directly from NativeThreadDarwin<br>
+#if 0<br>
+    bool            GetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, DNBRegisterValue *reg_value) const;<br>
+    bool            SetRegisterValue (nub_thread_t tid, uint32_t set, uint32_t reg, const DNBRegisterValue *reg_value) const;<br>
+    nub_size_t      GetRegisterContext (nub_thread_t tid, void *buf, size_t buf_len);<br>
+    nub_size_t      SetRegisterContext (nub_thread_t tid, const void *buf, size_t buf_len);<br>
+    uint32_t        SaveRegisterState (nub_thread_t tid);<br>
+    bool            RestoreRegisterState (nub_thread_t tid, uint32_t save_id);<br>
+#endif<br>
+<br>
+    const char *<br>
+    GetThreadInfo(lldb::tid_t tid) const;<br>
+<br>
+    void<br>
+    ProcessWillResume(<wbr>NativeProcessDarwin &process,<br>
+                      const ResumeActionList &thread_actions);<br>
+<br>
+    uint32_t<br>
+    ProcessDidStop(<wbr>NativeProcessDarwin &process);<br>
+<br>
+    bool<br>
+    NotifyException(MachException:<wbr>:Data& exc);<br>
+<br>
+    bool<br>
+    ShouldStop(bool &step_more);<br>
+<br>
+    // These methods will be accessed directly from NativeThreadDarwin<br>
+#if 0<br>
+    const char *    GetName (nub_thread_t tid);<br>
+    nub_state_t     GetState (nub_thread_t tid);<br>
+    nub_thread_t    SetCurrentThread (nub_thread_t tid);<br>
+#endif<br>
+<br>
+    // TODO: figure out if we need to add this to NativeThreadDarwin yet.<br>
+#if 0<br>
+    ThreadInfo::QoS GetRequestedQoS (nub_thread_t tid, nub_addr_t tsd, uint64_t dti_qos_class_index);<br>
+    nub_addr_t      GetPThreadT (nub_thread_t tid);<br>
+    nub_addr_t      GetDispatchQueueT (nub_thread_t tid);<br>
+    nub_addr_t      GetTSDAddressForThread (nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_<wbr>offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size);<br>
+#endif<br>
+<br>
+    // These methods will be accessed directly from NativeThreadDarwin<br>
+#if 0<br>
+    bool            GetThreadStoppedReason (nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const;<br>
+    void            DumpThreadStoppedReason (nub_thread_t tid) const;<br>
+    bool            GetIdentifierInfo (nub_thread_t tid, thread_identifier_info_data_t *ident_info);<br>
+#endif<br>
+<br>
+    size_t<br>
+    GetNumberOfThreads() const;<br>
+<br>
+    lldb::tid_t<br>
+    ThreadIDAtIndex(size_t idx) const;<br>
+<br>
+    lldb::tid_t<br>
+    GetCurrentThreadID();<br>
+<br>
+    NativeThreadDarwinSP<br>
+    GetCurrentThread();<br>
+<br>
+    void<br>
+    NotifyBreakpointChanged(const NativeBreakpointDarwin *bp);<br>
+<br>
+    uint32_t<br>
+    EnableHardwareBreakpoint(const NativeBreakpointDarwin *bp) const;<br>
+<br>
+    bool<br>
+    DisableHardwareBreakpoint(<wbr>const NativeBreakpointDarwin *bp) const;<br>
+<br>
+    uint32_t<br>
+    EnableHardwareWatchpoint(const NativeBreakpointDarwin *wp) const;<br>
+<br>
+    bool<br>
+    DisableHardwareWatchpoint(<wbr>const NativeBreakpointDarwin *wp) const;<br>
+<br>
+    uint32_t<br>
+    GetNumberOfSupportedHardwareWa<wbr>tchpoints() const;<br>
+<br>
+    size_t<br>
+    GetThreadIndexForThreadStopped<wbr>WithSignal(const int signo) const;<br>
+<br>
+    NativeThreadDarwinSP<br>
+    GetThreadByID(lldb::tid_t tid) const;<br>
+<br>
+    NativeThreadDarwinSP<br>
+    GetThreadByMachPortNumber(::<wbr>thread_t mach_port_number) const;<br>
+<br>
+    lldb::tid_t<br>
+    GetThreadIDByMachPortNumber(::<wbr>thread_t mach_port_number) const;<br>
+<br>
+    thread_t<br>
+    GetMachPortNumberByThreadID(<wbr>lldb::tid_t globally_unique_id) const;<br>
+<br>
+protected:<br>
+    typedef std::vector<<wbr>NativeThreadDarwinSP>  collection;<br>
+    typedef collection::iterator               iterator;<br>
+    typedef collection::const_iterator         const_iterator;<br>
+<br>
+    // Consider having this return an lldb_private::Error.<br>
+    uint32_t<br>
+    UpdateThreadList (NativeProcessDarwin &process, bool update,<br>
+                      collection *num_threads = nullptr);<br>
+<br>
+    collection                    m_threads;<br>
+    mutable std::recursive_mutex  m_threads_mutex;<br>
+    NativeThreadDarwinSP          m_current_thread;<br>
+    bool                          m_is_64_bit;<br>
+};<br>
+<br>
+} // namespace process_darwin<br>
+} // namespace lldb_private<br>
+<br>
+#endif // #ifndef __NativeThreadListDarwin_h__<br>
+<br>
<br>
Modified: lldb/trunk/source/Plugins/<wbr>Process/Linux/<wbr>NativeProcessLinux.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/Linux/<wbr>NativeProcessLinux.cpp?rev=<wbr>280604&r1=280603&r2=280604&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/Linux/<wbr>NativeProcessLinux.cpp (original)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/Linux/<wbr>NativeProcessLinux.cpp Sat Sep  3 19:18:56 2016<br>
@@ -108,27 +108,6 @@ static bool ProcessVmReadvSupported()<br>
<br>
 namespace<br>
 {<br>
-Error<br>
-ResolveProcessArchitecture(<wbr>lldb::pid_t pid, ArchSpec &arch)<br>
-{<br>
-    // Grab process info for the running process.<br>
-    ProcessInstanceInfo process_info;<br>
-    if (!Host::GetProcessInfo(pid, process_info))<br>
-        return Error("failed to get process info");<br>
-<br>
-    // Resolve the executable module.<br>
-    ModuleSpecList module_specs;<br>
-    if (!ObjectFile::<wbr>GetModuleSpecifications(<wbr>process_info.<wbr>GetExecutableFile(), 0, 0, module_specs))<br>
-        return Error("failed to get module specifications");<br>
-    assert(module_specs.GetSize() == 1);<br>
-<br>
-    arch = module_specs.<wbr>GetModuleSpecRefAtIndex(0).<wbr>GetArchitecture();<br>
-    if (arch.IsValid())<br>
-        return Error();<br>
-    else<br>
-        return Error("failed to retrieve a valid architecture from the exe module");<br>
-}<br>
-<br>
 void<br>
 MaybeLogLaunchInfo(const ProcessLaunchInfo &info)<br>
 {<br>
<br>
Modified: lldb/trunk/source/Plugins/<wbr>Process/gdb-remote/<wbr>GDBRemoteCommunicationServerCo<wbr>mmon.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/gdb-remote/<wbr>GDBRemoteCommunicationServerCo<wbr>mmon.cpp?rev=280604&r1=280603&<wbr>r2=280604&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/gdb-remote/<wbr>GDBRemoteCommunicationServerCo<wbr>mmon.cpp (original)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/gdb-remote/<wbr>GDBRemoteCommunicationServerCo<wbr>mmon.cpp Sat Sep  3 19:18:56 2016<br>
@@ -12,6 +12,11 @@<br>
 #include <errno.h><br>
<br>
 // C Includes<br>
+<br>
+#ifdef __APPLE__<br>
+#include <TargetConditionals.h><br>
+#endif<br>
+<br>
 // C++ Includes<br>
 #include <cstring><br>
 #include <chrono><br>
@@ -169,8 +174,11 @@ GDBRemoteCommunicationServerCo<wbr>mmon::Hand<br>
         response.PutCString(";");<br>
     }<br>
<br>
-    // Only send out MachO info when lldb-platform/llgs is running on a MachO host.<br>
 #if defined(__APPLE__)<br>
+    // For parity with debugserver, we'll include the vendor key.<br>
+    response.PutCString("vendor:<wbr>apple;");<br>
+<br>
+    // Send out MachO info.<br>
     uint32_t cpu = host_arch.GetMachOCPUType();<br>
     uint32_t sub = host_arch.GetMachOCPUSubType()<wbr>;<br>
     if (cpu != LLDB_INVALID_CPUTYPE)<br>
@@ -179,9 +187,26 @@ GDBRemoteCommunicationServerCo<wbr>mmon::Hand<br>
         response.Printf ("cpusubtype:%u;", sub);<br>
<br>
     if (cpu == ArchSpec::kCore_arm_any)<br>
-        response.Printf("watchpoint_<wbr>exceptions_received:before;");   // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.<br>
+    {<br>
+        // Indicate the OS type.<br>
+#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1<br>
+        response.PutCString("ostype:<wbr>tvos;");<br>
+#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1<br>
+        response.PutCString("ostype:<wbr>watchos;");<br>
+#else<br>
+        response.PutCString("ostype:<wbr>ios;");<br>
+#endif<br>
+<br>
+        // On arm, we use "synchronous" watchpoints which means the exception is<br>
+        // delivered before the instruction executes.<br>
+        response.PutCString("<wbr>watchpoint_exceptions_<wbr>received:before;");<br>
+    }<br>
     else<br>
+    {<br>
+        response.PutCString("ostype:<wbr>macosx;");<br>
         response.Printf("watchpoint_<wbr>exceptions_received:after;");<br>
+    }<br>
+<br>
 #else<br>
     if (host_arch.GetMachine() == llvm::Triple::aarch64 ||<br>
         host_arch.GetMachine() == llvm::Triple::aarch64_be ||<br>
<br>
Modified: lldb/trunk/source/Plugins/<wbr>Process/gdb-remote/<wbr>GDBRemoteCommunicationServerLL<wbr>GS.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Plugins/Process/gdb-remote/<wbr>GDBRemoteCommunicationServerLL<wbr>GS.cpp?rev=280604&r1=280603&<wbr>r2=280604&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Plugins/<wbr>Process/gdb-remote/<wbr>GDBRemoteCommunicationServerLL<wbr>GS.cpp (original)<br>
+++ lldb/trunk/source/Plugins/<wbr>Process/gdb-remote/<wbr>GDBRemoteCommunicationServerLL<wbr>GS.cpp Sat Sep  3 19:18:56 2016<br>
@@ -216,7 +216,8 @@ GDBRemoteCommunicationServerLL<wbr>GS::Launch<br>
     Error error;<br>
     {<br>
         std::lock_guard<std::<wbr>recursive_mutex> guard(m_debugged_process_<wbr>mutex);<br>
-        assert (!m_debugged_process_sp && "lldb-gdbserver creating debugged process but one already exists");<br>
+        assert (!m_debugged_process_sp && "lldb-server creating debugged "<br>
+                "process but one already exists");<br>
         error = NativeProcessProtocol::Launch(<br>
             m_process_launch_info,<br>
             *this,<br>
<br>
Modified: lldb/trunk/source/Target/<wbr>UnixSignals.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/UnixSignals.cpp?rev=280604&r1=280603&r2=280604&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/source/<wbr>Target/UnixSignals.cpp?rev=<wbr>280604&r1=280603&r2=280604&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/source/Target/<wbr>UnixSignals.cpp (original)<br>
+++ lldb/trunk/source/Target/<wbr>UnixSignals.cpp Sat Sep  3 19:18:56 2016<br>
@@ -89,6 +89,8 @@ UnixSignals::Reset ()<br>
     // This builds one standard set of Unix Signals.  If yours aren't quite in this<br>
     // order, you can either subclass this class, and use Add & Remove to change them<br>
     // or you can subclass and build them afresh in your constructor;<br>
+    //<br>
+    // Note: the signals below are the Darwin signals.  Do not change these!<br>
     m_signals.clear();<br>
     //        SIGNO  NAME          SUPPRESS STOP   NOTIFY DESCRIPTION<br>
     //        ====== ============  ======== ====== ====== ==============================<wbr>=====================<br>
<br>
Added: lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>Info.plist<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-server/Darwin/resources/lldb-server-Info.plist?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/tools/lldb-<wbr>server/Darwin/resources/lldb-<wbr>server-Info.plist?rev=280604&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>Info.plist (added)<br>
+++ lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>Info.plist Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,21 @@<br>
+<?xml version="1.0" encoding="UTF-8"?><br>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "<a href="http://www.apple.com/DTDs/PropertyList-1.0.dtd" rel="noreferrer" target="_blank">http://www.apple.com/DTDs/<wbr>PropertyList-1.0.dtd</a>"><br>
+<plist version="1.0"><br>
+<dict><br>
+       <key><wbr>CFBundleDevelopmentRegion</<wbr>key><br>
+       <string>English</string><br>
+       <key>CFBundleIdentifier</key><br>
+       <string>com.apple.lldb-server<<wbr>/string><br>
+       <key><wbr>CFBundleInfoDictionaryVersion<<wbr>/key><br>
+       <string>6.0</string><br>
+       <key>CFBundleName</key><br>
+       <string>lldb-server</string><br>
+       <key>CFBundleVersion</key><br>
+       <string>2</string><br>
+       <key>SecTaskAccess</key><br>
+       <array><br>
+               <string>allowed</string><br>
+               <string>debug</string><br>
+       </array><br>
+</dict><br>
+</plist><br>
<br>
Added: lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>entitlements.plist<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-server/Darwin/resources/lldb-server-entitlements.plist?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/tools/lldb-<wbr>server/Darwin/resources/lldb-<wbr>server-entitlements.plist?rev=<wbr>280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>entitlements.plist (added)<br>
+++ lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>entitlements.plist Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,28 @@<br>
+<?xml version="1.0" encoding="UTF-8"?><br>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "<a href="http://www.apple.com/DTDs/PropertyList-1.0.dtd" rel="noreferrer" target="_blank">http://www.apple.com/DTDs/<wbr>PropertyList-1.0.dtd</a>"><br>
+<plist version="1.0"><br>
+<dict><br>
+    <key>com.apple.springboard.<wbr>debugapplications</key><br>
+    <true/><br>
+    <key>com.apple.backboardd.<wbr>launchapplications</key><br>
+    <true/><br>
+    <key>com.apple.backboardd.<wbr>debugapplications</key><br>
+    <true/><br>
+    <key>com.apple.frontboard.<wbr>launchapplications</key><br>
+    <true/><br>
+    <key>com.apple.frontboard.<wbr>debugapplications</key><br>
+    <true/><br>
+    <key>run-unsigned-code</key><br>
+    <true/><br>
+    <key>seatbelt-profiles</key><br>
+    <array><br>
+        <string>debugserver</string><br>
+    </array><br>
+    <key>com.apple.diagnosticd.<wbr>diagnostic</key><br>
+    <true/><br>
+    <key>com.apple.security.<wbr>network.server</key><br>
+    <true/><br>
+    <key>com.apple.security.<wbr>network.client</key><br>
+    <true/><br>
+</dict><br>
+</plist><br>
<br>
Added: lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>macos-entitlements.plist<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-server/Darwin/resources/lldb-server-macos-entitlements.plist?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/tools/lldb-<wbr>server/Darwin/resources/lldb-<wbr>server-macos-entitlements.<wbr>plist?rev=280604&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>macos-entitlements.plist (added)<br>
+++ lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>macos-entitlements.plist Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,8 @@<br>
+<?xml version="1.0" encoding="UTF-8"?><br>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "<a href="http://www.apple.com/DTDs/PropertyList-1.0.dtd" rel="noreferrer" target="_blank">http://www.apple.com/DTDs/<wbr>PropertyList-1.0.dtd</a>"><br>
+<plist version="1.0"><br>
+<dict><br>
+    <key>com.apple.diagnosticd.<wbr>diagnostic</key><br>
+    <true/><br>
+</dict><br>
+</plist><br>
<br>
Added: lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>mig.defs<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-server/Darwin/resources/lldb-server-mig.defs?rev=280604&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/lldb/trunk/tools/lldb-<wbr>server/Darwin/resources/lldb-<wbr>server-mig.defs?rev=280604&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>mig.defs (added)<br>
+++ lldb/trunk/tools/lldb-server/<wbr>Darwin/resources/lldb-server-<wbr>mig.defs Sat Sep  3 19:18:56 2016<br>
@@ -0,0 +1,5 @@<br>
+/*<br>
+ * nub.defs<br>
+ */<br>
+<br>
+#import <mach/mach_exc.defs><br>
<br>
<br>
______________________________<wbr>_________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@lists.llvm.org">lldb-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/lldb-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">-Todd</div></div>
</div>