Add the ability for the task port to change when a process execs.
authorGreg Clayton <gclayton@apple.com>
Wed, 28 Sep 2016 21:07:34 +0000 (21:07 +0000)
committerGreg Clayton <gclayton@apple.com>
Wed, 28 Sep 2016 21:07:34 +0000 (21:07 +0000)
<rdar://problem/28476369>

llvm-svn: 282632

lldb/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py
lldb/tools/debugserver/source/MacOSX/MachException.cpp
lldb/tools/debugserver/source/MacOSX/MachTask.h
lldb/tools/debugserver/source/MacOSX/MachTask.mm

index e89d99c21beba5566a7b90cd00a3a46ebb09bacb..98b002eb288bcb923f53c67e6d011047359104a3 100644 (file)
@@ -27,7 +27,6 @@ class ExecTestCase(TestBase):
     mydir = TestBase.compute_mydir(__file__)
 
     @skipUnlessDarwin
-    @expectedFailureAll(oslist=["macosx"], bugnumber="rdar://28476369")
     def test(self):
         if self.getArchitecture() == 'x86_64':
             source = os.path.join(os.getcwd(), "main.cpp")
index 09849312fbb7473889bca8a560fca508fc52d4fc..f6e778232b82f393ed1bf55982b795c1474bf672 100644 (file)
@@ -106,15 +106,30 @@ catch_mach_exception_raise(mach_port_t exc_port, mach_port_t thread_port,
                    (uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD),
                    (uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD));
   }
+  g_message->exc_type = 0;
+  g_message->exc_data.clear();
 
   if (task_port == g_message->task_port) {
     g_message->task_port = task_port;
     g_message->thread_port = thread_port;
     g_message->exc_type = exc_type;
-    g_message->exc_data.resize(exc_data_count);
-    ::memcpy(&g_message->exc_data[0], exc_data,
-             g_message->exc_data.size() * sizeof(mach_exception_data_type_t));
+    for (mach_msg_type_number_t i=0; i<exc_data_count; ++i)
+      g_message->exc_data.push_back(exc_data[i]);
     return KERN_SUCCESS;
+  } else if (!MachTask::IsValid(g_message->task_port)) {
+    // Our original exception port isn't valid anymore check for a SIGTRAP
+    if (exc_type == EXC_SOFTWARE && exc_data_count == 2 &&
+        exc_data[0] == EXC_SOFT_SIGNAL && exc_data[1] == SIGTRAP) {
+      // We got a SIGTRAP which indicates we might have exec'ed and possibly
+      // lost our old task port during the exec, so we just need to switch over
+      // to using this new task port
+      g_message->task_port = task_port;
+      g_message->thread_port = thread_port;
+      g_message->exc_type = exc_type;
+      for (mach_msg_type_number_t i=0; i<exc_data_count; ++i)
+        g_message->exc_data.push_back(exc_data[i]);
+      return KERN_SUCCESS;
+    }
   }
   return KERN_FAILURE;
 }
index 2fdb22f8e562ed152aa0e72052f7f261acfe9ded..1e0e2af9a92b815217d5feb9809e8113bc5f2d20 100644 (file)
@@ -82,6 +82,7 @@ public:
   bool IsValid() const;
   static bool IsValid(task_t task);
   static void *ExceptionThread(void *arg);
+  void TaskPortChanged(task_t task);
   task_t TaskPort() const { return m_task; }
   task_t TaskPortForProcessID(DNBError &err, bool force = false);
   static task_t TaskPortForProcessID(pid_t pid, DNBError &err,
index f0f086ecbd987a345667685e9273f2cef74ebaa7..37897a5a6acd799f3f88ecaff4ddf34689f4c781 100644 (file)
@@ -867,6 +867,16 @@ void *MachTask::ExceptionThread(void *arg) {
       // TODO: notify of error?
     } else {
       if (exception_message.CatchExceptionRaise(task)) {
+        if (exception_message.state.task_port != task) {
+          if (exception_message.state.IsValid()) {
+            // We exec'ed and our task port changed on us.
+            DNBLogThreadedIf(LOG_EXCEPTIONS,
+                             "task port changed from 0x%4.4x to 0x%4.4x",
+                             task, exception_message.state.task_port);
+            task = exception_message.state.task_port;
+            mach_task->TaskPortChanged(exception_message.state.task_port);
+          }
+        }
         ++num_exceptions_received;
         mach_proc->ExceptionMessageReceived(exception_message);
       }
@@ -984,3 +994,8 @@ nub_bool_t MachTask::DeallocateMemory(nub_addr_t addr) {
 }
 
 nub_size_t MachTask::PageSize() { return m_vm_memory.PageSize(m_task); }
+
+void MachTask::TaskPortChanged(task_t task)
+{
+  m_task = task;
+}