gdb: change single_displaced_buffer_manager into multiple_displaced_buffer_manager
[deliverable/binutils-gdb.git] / gdb / displaced-stepping.c
index cbf2425e370e0ca086e16083cb791d84b2219dd3..f373be79642fcf52234ff7808962932812534bb0 100644 (file)
 displaced_step_copy_insn_closure::~displaced_step_copy_insn_closure() = default;
 
 displaced_step_prepare_status
-single_displaced_buffer_manager::prepare (thread_info *thread)
+multiple_displaced_buffer_manager::prepare (thread_info *thread)
 {
-  /* Is a thread currently using the buffer?  */
-  if (m_current_thread != nullptr)
+  gdb_assert (!thread->displaced_step_state.in_progress ());
+  displaced_step_buffer_state *buffer = nullptr;
+
+  /* Sanity check.  */
+  for (displaced_step_buffer_state &buf : m_buffers)
+    gdb_assert (buf.m_current_thread != thread);
+
+  /* Search for an unused buffer.  */
+  for (displaced_step_buffer_state &candidate : m_buffers)
     {
-      /* If so, it better not be this thread.  */
-      gdb_assert (thread != m_current_thread);
-      return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
+      if (candidate.m_current_thread == nullptr)
+       {
+         buffer = &candidate;
+         break;
+       }
     }
 
+  if (buffer == nullptr)
+    return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
+
   gdbarch *arch = thread->arch ();
+
+  if (debug_displaced)
+    fprintf_unfiltered (gdb_stdlog, "displaced: selected buffer at %s\n",
+                       paddress (arch, buffer->m_buffer_addr));
+
   struct regcache *regcache = thread->regcache ();
   ULONGEST len = gdbarch_max_insn_length (arch);
-  m_original_pc = regcache_read_pc (regcache);
+  buffer->m_original_pc = regcache_read_pc (regcache);
 
   /* Save the original contents of the displaced stepping buffer.  */
-  m_saved_copy.resize (len);
+  buffer->m_saved_copy.resize (len);
 
-  int status = target_read_memory (m_buffer_addr, m_saved_copy.data (), len);
+  int status = target_read_memory (buffer->m_buffer_addr, buffer->m_saved_copy.data (), len);
   if (status != 0)
     throw_error (MEMORY_ERROR,
                 _("Error accessing memory address %s (%s) for "
                   "displaced-stepping scratch space."),
-                paddress (arch, m_buffer_addr), safe_strerror (status));
+                paddress (arch, buffer->m_buffer_addr), safe_strerror (status));
 
   if (debug_displaced)
     {
       fprintf_unfiltered (gdb_stdlog, "displaced: saved %s: ",
-                         paddress (arch, m_buffer_addr));
-      displaced_step_dump_bytes (gdb_stdlog, m_saved_copy.data (), len);
+                         paddress (arch, buffer->m_buffer_addr));
+      displaced_step_dump_bytes (gdb_stdlog, buffer->m_saved_copy.data (), len);
     };
 
-  m_copy_insn_closure = gdbarch_displaced_step_copy_insn (arch,
-                                                         m_original_pc,
-                                                         m_buffer_addr,
-                                                         regcache);
-  if (m_copy_insn_closure == nullptr)
+  buffer->m_copy_insn_closure
+    = gdbarch_displaced_step_copy_insn (arch, buffer->m_original_pc,
+                                       buffer->m_buffer_addr, regcache);
+  if (buffer->m_copy_insn_closure == nullptr)
     {
       /* The architecture doesn't know how or want to displaced step
         this instruction or instruction sequence.  Fallback to
@@ -58,19 +74,19 @@ single_displaced_buffer_manager::prepare (thread_info *thread)
   try
     {
       /* Resume execution at the copy.  */
-      regcache_write_pc (regcache, m_buffer_addr);
+      regcache_write_pc (regcache, buffer->m_buffer_addr);
     }
   catch (...)
     {
       /* Failed to write the PC.  Release the architecture's displaced
          stepping resources and the thread's displaced stepping state.  */
-      m_copy_insn_closure.reset ();
+      buffer->m_copy_insn_closure.reset ();
 
       return DISPLACED_STEP_PREPARE_STATUS_ERROR;
     }
 
   /* This marks the buffer as being in use.  */
-  m_current_thread = thread;
+  buffer->m_current_thread = thread;
 
   return DISPLACED_STEP_PREPARE_STATUS_OK;
 }
@@ -103,32 +119,46 @@ displaced_step_instruction_executed_successfully (gdbarch *arch, gdb_signal sign
 }
 
 displaced_step_finish_status
-single_displaced_buffer_manager::finish (gdbarch *arch, thread_info *thread,
-                                        gdb_signal sig)
+multiple_displaced_buffer_manager::finish (gdbarch *arch, thread_info *thread,
+                                          gdb_signal sig)
 {
   displaced_step_finish_status status;
+  displaced_step_buffer_state *buffer = nullptr;
 
-  gdb_assert (thread == m_current_thread);
+  gdb_assert (thread->displaced_step_state.in_progress ());
+
+  /* Find the buffer this thread was using.  */
+  for (displaced_step_buffer_state &candidate : m_buffers)
+    {
+      if (thread == candidate.m_current_thread)
+       {
+         buffer = &candidate;
+         break;
+       }
+    }
+
+  gdb_assert (buffer != nullptr);
 
   ULONGEST len = gdbarch_max_insn_length (arch);
 
-  write_memory_ptid (thread->ptid, m_buffer_addr,
-                    m_saved_copy.data (), len);
+  /* Restore memory of the buffer.  */
+  write_memory_ptid (thread->ptid, buffer->m_buffer_addr,
+                    buffer->m_saved_copy.data (), len);
   if (debug_displaced)
     fprintf_unfiltered (gdb_stdlog, "displaced: restored %s %s\n",
                        target_pid_to_str (thread->ptid).c_str (),
-                       paddress (arch, m_buffer_addr));
+                       paddress (arch, buffer->m_buffer_addr));
 
   regcache *rc = get_thread_regcache (thread);
 
   bool instruction_executed_successfully
     = displaced_step_instruction_executed_successfully (arch, sig);
 
-
   if (instruction_executed_successfully)
     {
-      gdbarch_displaced_step_fixup (arch, m_copy_insn_closure.get (), m_original_pc,
-                                   m_buffer_addr, rc);
+      gdbarch_displaced_step_fixup (arch, buffer->m_copy_insn_closure.get (),
+                                   buffer->m_original_pc,
+                                   buffer->m_buffer_addr, rc);
       status = DISPLACED_STEP_FINISH_STATUS_OK;
     }
   else
@@ -136,13 +166,13 @@ single_displaced_buffer_manager::finish (gdbarch *arch, thread_info *thread,
       /* Since the instruction didn't complete, all we can do is relocate the
         PC.  */
       CORE_ADDR pc = regcache_read_pc (rc);
-      pc = m_original_pc + (pc - m_buffer_addr);
+      pc = buffer->m_original_pc + (pc - buffer->m_buffer_addr);
       regcache_write_pc (rc, pc);
       status = DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED;
     }
 
-  m_copy_insn_closure.reset ();
-  m_current_thread = nullptr;
+  buffer->m_copy_insn_closure.reset ();
+  buffer->m_current_thread = nullptr;
 
   return status;
 }
This page took 0.025406 seconds and 4 git commands to generate.