Fix inferior memory reading in GDBServer for arm/aarch32
[deliverable/binutils-gdb.git] / gdb / gdbserver / nto-low.c
index a2ddd44d6bd850c9259e6c595d43dcaab2f5ac53..6229b4c1b4ff446980d28e353d88ddab10906c88 100644 (file)
@@ -1,7 +1,6 @@
 /* QNX Neutrino specific low level interface, for the remote server
    for GDB.
-   Copyright (C) 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 2009-2017 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 
 
 #include "server.h"
+#include "gdbthread.h"
 #include "nto-low.h"
+#include "hostio.h"
 
 #include <limits.h>
 #include <fcntl.h>
 #include <spawn.h>
 #include <sys/procfs.h>
 #include <sys/auxv.h>
-#include <stdarg.h>
 #include <sys/iomgr.h>
 #include <sys/neutrino.h>
 
@@ -35,6 +35,8 @@
 extern int using_threads;
 int using_threads = 1;
 
+const struct target_desc *nto_tdesc;
+
 static void
 nto_trace (const char *fmt, ...)
 {
@@ -175,7 +177,7 @@ do_attach (pid_t pid)
       close (nto_inferior.ctl_fd);
       init_nto_inferior (&nto_inferior);
     }
-  snprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid);
+  xsnprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid);
   nto_inferior.ctl_fd = open (nto_inferior.nto_procfs_path, O_RDWR);
   if (nto_inferior.ctl_fd == -1)
     {
@@ -203,11 +205,13 @@ do_attach (pid_t pid)
       && (status.flags & _DEBUG_FLAG_STOPPED))
     {
       ptid_t ptid;
+      struct process_info *proc;
 
       kill (pid, SIGCONT);
       ptid = ptid_build (status.pid, status.tid, 0);
       the_low_target.arch_setup ();
-      add_process (status.pid, 1);
+      proc = add_process (status.pid, 1);
+      proc->tdesc = nto_tdesc;
       TRACE ("Adding thread: pid=%d tid=%ld\n", status.pid,
             ptid_get_lwp (ptid));
       nto_find_new_threads (&nto_inferior);
@@ -407,6 +411,12 @@ nto_detach (int pid)
   return 0;
 }
 
+static void
+nto_mourn (struct process_info *process)
+{
+  remove_process (process);
+}
+
 /* Check if the given thread is alive.  
 
    Return 1 if alive, 0 otherwise.  */
@@ -526,14 +536,14 @@ nto_wait (ptid_t ptid,
     {
       TRACE ("SSTEP\n");
       ourstatus->kind = TARGET_WAITKIND_STOPPED;
-      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+      ourstatus->value.sig = GDB_SIGNAL_TRAP;
     }
   /* Was it a breakpoint?  */
   else if (status.flags & trace_mask)
     {
       TRACE ("STOPPED\n");
       ourstatus->kind = TARGET_WAITKIND_STOPPED;
-      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+      ourstatus->value.sig = GDB_SIGNAL_TRAP;
     }
   else if (status.flags & _DEBUG_FLAG_ISTOP)
     {
@@ -544,7 +554,7 @@ nto_wait (ptid_t ptid,
          TRACE ("  SIGNALLED\n");
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
          ourstatus->value.sig =
-           target_signal_from_host (status.info.si_signo);
+           gdb_signal_from_host (status.info.si_signo);
          nto_inferior.exit_signo = ourstatus->value.sig;
          break;
        case _DEBUG_WHY_FAULTED:
@@ -558,7 +568,7 @@ nto_wait (ptid_t ptid,
          else
            {
              ourstatus->value.sig =
-               target_signal_from_host (status.info.si_signo);
+               gdb_signal_from_host (status.info.si_signo);
              nto_inferior.exit_signo = ourstatus->value.sig;
            }
          break;
@@ -589,7 +599,7 @@ nto_wait (ptid_t ptid,
          TRACE ("REQUESTED\n");
          /* We are assuming a requested stop is due to a SIGINT.  */
          ourstatus->kind = TARGET_WAITKIND_STOPPED;
-         ourstatus->value.sig = TARGET_SIGNAL_INT;
+         ourstatus->value.sig = GDB_SIGNAL_INT;
          nto_inferior.exit_signo = 0;
          break;
        }
@@ -602,7 +612,7 @@ nto_wait (ptid_t ptid,
    If REGNO is -1, fetch all registers, or REGNO register only otherwise.  */
 
 static void
-nto_fetch_registers (int regno)
+nto_fetch_registers (struct regcache *regcache, int regno)
 {
   int regsize;
   procfs_greg greg;
@@ -612,12 +622,12 @@ nto_fetch_registers (int regno)
   if (regno >= the_low_target.num_regs)
     return;
 
-  if (current_inferior == NULL)
+  if (current_thread == NULL)
     {
-      TRACE ("current_inferior is NULL\n");
+      TRACE ("current_thread is NULL\n");
       return;
     }
-  ptid = thread_to_gdb_id (current_inferior);
+  ptid = thread_to_gdb_id (current_thread);
   if (!nto_set_thread (ptid))
     return;
 
@@ -630,7 +640,8 @@ nto_fetch_registers (int regno)
            {
              const unsigned int registeroffset
                = the_low_target.register_offset (regno);
-             supply_register (regno, ((char *)&greg) + registeroffset);
+             supply_register (regcache, regno,
+                              ((char *)&greg) + registeroffset);
            }
        }
       else
@@ -639,7 +650,7 @@ nto_fetch_registers (int regno)
            = the_low_target.register_offset (regno);
          if (registeroffset == -1)
            return;
-         supply_register (regno, ((char *)&greg) + registeroffset);
+         supply_register (regcache, regno, ((char *)&greg) + registeroffset);
        }
     }
   else
@@ -650,7 +661,7 @@ nto_fetch_registers (int regno)
    We always store all registers, regardless of REGNO.  */
 
 static void
-nto_store_registers (int regno)
+nto_store_registers (struct regcache *regcache, int regno)
 {
   procfs_greg greg;
   int err;
@@ -658,12 +669,12 @@ nto_store_registers (int regno)
 
   TRACE ("%s (regno:%d)\n", __func__, regno);
 
-  if (current_inferior == NULL)
+  if (current_thread == NULL)
     {
-      TRACE ("current_inferior is NULL\n");
+      TRACE ("current_thread is NULL\n");
       return;
     }
-  ptid = thread_to_gdb_id (current_inferior);
+  ptid = thread_to_gdb_id (current_thread);
   if (!nto_set_thread (ptid))
     return;
 
@@ -672,7 +683,7 @@ nto_store_registers (int regno)
     {
       const unsigned int regoffset
        = the_low_target.register_offset (regno);
-      collect_register (regno, ((char *)&greg) + regoffset);
+      collect_register (regcache, regno, ((char *)&greg) + regoffset);
     }
   err = devctl (nto_inferior.ctl_fd, DCMD_PROC_SETGREG, &greg, sizeof (greg),
                0);
@@ -759,30 +770,46 @@ nto_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
   return nto_read_auxv_from_initial_stack (initial_stack, myaddr, len);
 }
 
-/* Insert {break/watch}point at address ADDR.
-   TYPE must be in '0'..'4' range.  LEN is not used.  */
+static int
+nto_supports_z_point_type (char z_type)
+{
+  switch (z_type)
+    {
+    case Z_PACKET_SW_BP:
+    case Z_PACKET_HW_BP:
+    case Z_PACKET_WRITE_WP:
+    case Z_PACKET_READ_WP:
+    case Z_PACKET_ACCESS_WP:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
+/* Insert {break/watch}point at address ADDR.  SIZE is not used.  */
 
 static int
-nto_insert_point (char type, CORE_ADDR addr, int len)
+nto_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
+                 int size, struct raw_breakpoint *bp)
 {
   int wtype = _DEBUG_BREAK_HW; /* Always request HW.  */
 
-  TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
+  TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, size);
   switch (type)
     {
-    case '0': /* software-breakpoint */
+    case raw_bkpt_type_sw:
       wtype = _DEBUG_BREAK_EXEC;
       break;
-    case '1': /* hardware-breakpoint */
+    case raw_bkpt_type_hw:
       wtype |= _DEBUG_BREAK_EXEC;
       break;
-    case '2':  /* write watchpoint */
+    case raw_bkpt_type_write_wp:
       wtype |= _DEBUG_BREAK_RW;
       break;
-    case '3':  /* read watchpoint */
+    case raw_bkpt_type_read_wp:
       wtype |= _DEBUG_BREAK_RD;
       break;
-    case '4':  /* access watchpoint */
+    case raw_bkpt_type_access_wp:
       wtype |= _DEBUG_BREAK_RW;
       break;
     default:
@@ -791,30 +818,30 @@ nto_insert_point (char type, CORE_ADDR addr, int len)
   return nto_breakpoint (addr, wtype, 0);
 }
 
-/* Remove {break/watch}point at address ADDR.
-   TYPE must be in '0'..'4' range.  LEN is not used.  */
+/* Remove {break/watch}point at address ADDR.  SIZE is not used.  */
 
 static int
-nto_remove_point (char type, CORE_ADDR addr, int len)
+nto_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
+                 int size, struct raw_breakpoint *bp)
 {
   int wtype = _DEBUG_BREAK_HW; /* Always request HW.  */
 
-  TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len);
+  TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, size);
   switch (type)
     {
-    case '0': /* software-breakpoint */
+    case raw_bkpt_type_sw:
       wtype = _DEBUG_BREAK_EXEC;
       break;
-    case '1': /* hardware-breakpoint */
+    case raw_bkpt_type_hw:
       wtype |= _DEBUG_BREAK_EXEC;
       break;
-    case '2':  /* write watchpoint */
+    case raw_bkpt_type_write_wp:
       wtype |= _DEBUG_BREAK_RW;
       break;
-    case '3':  /* read watchpoint */
+    case raw_bkpt_type_read_wp:
       wtype |= _DEBUG_BREAK_RD;
       break;
-    case '4':  /* access watchpoint */
+    case raw_bkpt_type_access_wp:
       wtype |= _DEBUG_BREAK_RW;
       break;
     default:
@@ -834,11 +861,11 @@ nto_stopped_by_watchpoint (void)
   int ret = 0;
 
   TRACE ("%s\n", __func__);
-  if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
+  if (nto_inferior.ctl_fd != -1 && current_thread != NULL)
     {
       ptid_t ptid;
 
-      ptid = thread_to_gdb_id (current_inferior);
+      ptid = thread_to_gdb_id (current_thread);
       if (nto_set_thread (ptid))
        {
          const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR
@@ -866,11 +893,11 @@ nto_stopped_data_address (void)
   CORE_ADDR ret = (CORE_ADDR)0;
 
   TRACE ("%s\n", __func__);
-  if (nto_inferior.ctl_fd != -1 && current_inferior != NULL)
+  if (nto_inferior.ctl_fd != -1 && current_thread != NULL)
     {
       ptid_t ptid;
 
-      ptid = thread_to_gdb_id (current_inferior);
+      ptid = thread_to_gdb_id (current_thread);
 
       if (nto_set_thread (ptid))
        {
@@ -894,26 +921,44 @@ nto_supports_non_stop (void)
   return 0;
 }
 
+/* Implementation of the target_ops method "sw_breakpoint_from_kind".  */
+
+static const gdb_byte *
+nto_sw_breakpoint_from_kind (int kind, int *size)
+{
+  *size = the_low_target.breakpoint_len;
+  return the_low_target.breakpoint;
+}
 
 
 static struct target_ops nto_target_ops = {
   nto_create_inferior,
+  NULL,  /* post_create_inferior */
   nto_attach,
   nto_kill,
   nto_detach,
+  nto_mourn,
   NULL, /* nto_join */
   nto_thread_alive,
   nto_resume,
   nto_wait,
   nto_fetch_registers,
   nto_store_registers,
+  NULL, /* prepare_to_access_memory */
+  NULL, /* done_accessing_memory */
   nto_read_memory,
   nto_write_memory,
   NULL, /* nto_look_up_symbols */
   nto_request_interrupt,
   nto_read_auxv,
+  nto_supports_z_point_type,
   nto_insert_point,
   nto_remove_point,
+  NULL, /* stopped_by_sw_breakpoint */
+  NULL, /* supports_stopped_by_sw_breakpoint */
+  NULL, /* stopped_by_hw_breakpoint */
+  NULL, /* supports_stopped_by_hw_breakpoint */
+  target_can_do_hardware_single_step,
   nto_stopped_by_watchpoint,
   nto_stopped_data_address,
   NULL, /* nto_read_offsets */
@@ -924,7 +969,42 @@ static struct target_ops nto_target_ops = {
   NULL, /* xfer_siginfo */
   nto_supports_non_stop,
   NULL, /* async */
-  NULL  /* start_non_stop */
+  NULL, /* start_non_stop */
+  NULL, /* supports_multi_process */
+  NULL, /* supports_fork_events */
+  NULL, /* supports_vfork_events */
+  NULL, /* supports_exec_events */
+  NULL, /* handle_new_gdb_connection */
+  NULL, /* handle_monitor_command */
+  NULL, /* core_of_thread */
+  NULL, /* read_loadmap */
+  NULL, /* process_qsupported */
+  NULL, /* supports_tracepoints */
+  NULL, /* read_pc */
+  NULL, /* write_pc */
+  NULL, /* thread_stopped */
+  NULL, /* get_tib_address */
+  NULL, /* pause_all */
+  NULL, /* unpause_all */
+  NULL, /* stabilize_threads */
+  NULL, /* install_fast_tracepoint_jump_pad */
+  NULL, /* emit_ops */
+  NULL, /* supports_disable_randomization */
+  NULL, /* get_min_fast_tracepoint_insn_len */
+  NULL, /* qxfer_libraries_svr4 */
+  NULL, /* support_agent */
+  NULL, /* support_btrace */
+  NULL, /* enable_btrace */
+  NULL, /* disable_btrace */
+  NULL, /* read_btrace */
+  NULL, /* read_btrace_conf */
+  NULL, /* supports_range_stepping */
+  NULL, /* pid_to_exec_file */
+  NULL, /* multifs_open */
+  NULL, /* multifs_unlink */
+  NULL, /* multifs_readlink */
+  NULL, /* breakpoint_kind_from_pc */
+  nto_sw_breakpoint_from_kind,
 };
 
 
@@ -938,8 +1018,6 @@ initialize_low (void)
 
   TRACE ("%s\n", __func__);
   set_target_ops (&nto_target_ops);
-  set_breakpoint_data (the_low_target.breakpoint,
-                      the_low_target.breakpoint_len);
 
   /* We use SIGUSR1 to gain control after we block waiting for a process.
      We use sigwaitevent to wait.  */
This page took 0.029073 seconds and 4 git commands to generate.