]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/mips-linux-nat.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / gdb / mips-linux-nat.c
index 39bd03a5e9efe62a11349a23e631416d16dd275d..38ff461a35b3955780e6ce49c69b0e05c4b27136 100644 (file)
@@ -1,6 +1,6 @@
 /* Native-dependent code for GNU/Linux on MIPS processors.
 
-   Copyright (C) 2001-2018 Free Software Foundation, Inc.
+   Copyright (C) 2001-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -59,9 +59,9 @@ public:
   int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
                         struct expression *) override;
 
-  int stopped_by_watchpoint () override;
+  bool stopped_by_watchpoint () override;
 
-  int stopped_data_address (CORE_ADDR *) override;
+  bool stopped_data_address (CORE_ADDR *) override;
 
   int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
 
@@ -72,6 +72,9 @@ protected:
   CORE_ADDR register_u_offset (struct gdbarch *gdbarch,
                               int regno, int store_p) override;
 
+  /* Override linux_nat_target low methods.  */
+  void low_new_thread (struct lwp_info *lp) override;
+
 private:
   /* Helpers.  See definitions.  */
   void mips64_regsets_store_registers (struct regcache *regcache,
@@ -142,6 +145,11 @@ mips64_linux_register_addr (struct gdbarch *gdbarch, int regno, int store)
   if (regno < 0 || regno >= gdbarch_num_regs (gdbarch))
     error (_("Bogon register number %d."), regno);
 
+  /* On n32 we can't access 64-bit registers via PTRACE_PEEKUSR
+     or PTRACE_POKEUSR.  */
+  if (register_size (gdbarch, regno) > sizeof (PTRACE_TYPE_RET))
+    return (CORE_ADDR) -1;
+
   if (regno > MIPS_ZERO_REGNUM && regno < MIPS_ZERO_REGNUM + 32)
     regaddr = regno;
   else if ((regno >= mips_regnum (gdbarch)->fp0)
@@ -216,22 +224,14 @@ fill_gregset (const struct regcache *regcache,
 void
 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
 {
-  if (mips_isa_regsize (regcache->arch ()) == 4)
-    mips_supply_fpregset (regcache, (const mips_elf_fpregset_t *) fpregsetp);
-  else
-    mips64_supply_fpregset (regcache,
-                           (const mips64_elf_fpregset_t *) fpregsetp);
+  mips64_supply_fpregset (regcache, (const mips64_elf_fpregset_t *) fpregsetp);
 }
 
 void
 fill_fpregset (const struct regcache *regcache,
               gdb_fpregset_t *fpregsetp, int regno)
 {
-  if (mips_isa_regsize (regcache->arch ()) == 4)
-    mips_fill_fpregset (regcache, (mips_elf_fpregset_t *) fpregsetp, regno);
-  else
-    mips64_fill_fpregset (regcache,
-                         (mips64_elf_fpregset_t *) fpregsetp, regno);
+  mips64_fill_fpregset (regcache, (mips64_elf_fpregset_t *) fpregsetp, regno);
 }
 
 
@@ -270,7 +270,7 @@ mips_linux_nat_target::mips64_regsets_fetch_registers
   else
     is_dsp = 0;
 
-  tid = get_ptrace_pid (regcache_get_ptid (regcache));
+  tid = get_ptrace_pid (regcache->ptid ());
 
   if (regno == -1 || (!is_fp && !is_dsp))
     {
@@ -357,7 +357,7 @@ mips_linux_nat_target::mips64_regsets_store_registers
   else
     is_dsp = 0;
 
-  tid = get_ptrace_pid (regcache_get_ptid (regcache));
+  tid = get_ptrace_pid (regcache->ptid ());
 
   if (regno == -1 || (!is_fp && !is_dsp))
     {
@@ -413,7 +413,13 @@ mips_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
   /* If we know, or just found out, that PTRACE_GETREGS does not work, fall
      back to PTRACE_PEEKUSER.  */
   if (!have_ptrace_regsets)
-    linux_nat_trad_target::fetch_registers (regcache, regnum);
+    {
+      linux_nat_trad_target::fetch_registers (regcache, regnum);
+
+      /* Fill the inaccessible zero register with zero.  */
+      if (regnum == MIPS_ZERO_REGNUM || regnum == -1)
+       regcache->raw_supply_zeroed (MIPS_ZERO_REGNUM);
+    }
 }
 
 /* Store REGNO (or all registers if REGNO == -1) to the target
@@ -452,11 +458,7 @@ mips_linux_nat_target::read_description ()
 
   if (have_dsp < 0)
     {
-      int tid;
-
-      tid = ptid_get_lwp (inferior_ptid);
-      if (tid == 0)
-       tid = ptid_get_pid (inferior_ptid);
+      int tid = get_ptrace_pid (inferior_ptid);
 
       errno = 0;
       ptrace (PTRACE_PEEKUSER, tid, DSP_CONTROL, 0);
@@ -537,7 +539,7 @@ mips_linux_nat_target::can_use_hw_breakpoint (enum bptype type,
   int i;
   uint32_t wanted_mask, irw_mask;
 
-  if (!mips_linux_read_watch_registers (ptid_get_lwp (inferior_ptid),
+  if (!mips_linux_read_watch_registers (inferior_ptid.lwp (),
                                        &watch_readback,
                                        &watch_readback_valid, 0))
     return 0;
@@ -572,36 +574,36 @@ mips_linux_nat_target::can_use_hw_breakpoint (enum bptype type,
    stopped by watchpoint.  The watchhi R and W bits indicate the watch
    register triggered.  */
 
-int
+bool
 mips_linux_nat_target::stopped_by_watchpoint ()
 {
   int n;
   int num_valid;
 
-  if (!mips_linux_read_watch_registers (ptid_get_lwp (inferior_ptid),
+  if (!mips_linux_read_watch_registers (inferior_ptid.lwp (),
                                        &watch_readback,
                                        &watch_readback_valid, 1))
-    return 0;
+    return false;
 
   num_valid = mips_linux_watch_get_num_valid (&watch_readback);
 
   for (n = 0; n < MAX_DEBUG_REGISTER && n < num_valid; n++)
     if (mips_linux_watch_get_watchhi (&watch_readback, n) & (R_MASK | W_MASK))
-      return 1;
+      return true;
 
-  return 0;
+  return false;
 }
 
 /* Target to_stopped_data_address implementation.  Set the address
    where the watch triggered (if known).  Return 1 if the address was
    known.  */
 
-int
+bool
 mips_linux_nat_target::stopped_data_address (CORE_ADDR *paddr)
 {
   /* On mips we don't know the low order 3 bits of the data address,
      so we must return false.  */
-  return 0;
+  return false;
 }
 
 /* Target to_region_ok_for_hw_watchpoint implementation.  Return 1 if
@@ -613,7 +615,7 @@ mips_linux_nat_target::region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
   struct pt_watch_regs dummy_regs;
   int i;
 
-  if (!mips_linux_read_watch_registers (ptid_get_lwp (inferior_ptid),
+  if (!mips_linux_read_watch_registers (inferior_ptid.lwp (),
                                        &watch_readback,
                                        &watch_readback_valid, 0))
     return 0;
@@ -635,18 +637,18 @@ write_watchpoint_regs (void)
 
   ALL_LWPS (lp)
     {
-      tid = ptid_get_lwp (lp->ptid);
+      tid = lp->ptid.lwp ();
       if (ptrace (PTRACE_SET_WATCH_REGS, tid, &watch_mirror, NULL) == -1)
        perror_with_name (_("Couldn't write debug register"));
     }
   return 0;
 }
 
-/* linux_nat new_thread implementation.  Write the mirrored watch
- register values for the new thread.  */
+/* linux_nat_target::low_new_thread implementation.  Write the
  mirrored watch register values for the new thread.  */
 
-static void
-mips_linux_new_thread (struct lwp_info *lp)
+void
+mips_linux_nat_target::low_new_thread (struct lwp_info *lp)
 {
   long tid = lp->ptid.lwp ();
 
@@ -671,10 +673,9 @@ mips_linux_nat_target::insert_watchpoint (CORE_ADDR addr, int len,
   struct mips_watchpoint *new_watch;
   struct mips_watchpoint **pw;
 
-  int i;
   int retval;
 
-  if (!mips_linux_read_watch_registers (ptid_get_lwp (inferior_ptid),
+  if (!mips_linux_read_watch_registers (inferior_ptid.lwp (),
                                        &watch_readback,
                                        &watch_readback_valid, 0))
     return -1;
@@ -782,8 +783,9 @@ mips_linux_nat_target::close ()
   linux_nat_trad_target::close ();
 }
 
+void _initialize_mips_linux_nat ();
 void
-_initialize_mips_linux_nat (void)
+_initialize_mips_linux_nat ()
 {
   add_setshow_boolean_cmd ("show-debug-regs", class_maintenance,
                           &show_debug_regs, _("\
@@ -799,7 +801,5 @@ triggers a breakpoint or watchpoint."),
                           &maintenance_show_cmdlist);
 
   linux_target = &the_mips_linux_nat_target;
-  add_target (&the_mips_linux_nat_target);
-  linux_nat_set_new_thread (&the_mips_linux_nat_target,
-                           mips_linux_new_thread);
+  add_inf_child_target (&the_mips_linux_nat_target);
 }