Home | History | Annotate | Line # | Download | only in gdb
      1 /* Generic GNU/Linux target using traditional ptrace register access.
      2 
      3    Copyright (C) 1988-2024 Free Software Foundation, Inc.
      4 
      5    This file is part of GDB.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19 
     20 #include "linux-nat-trad.h"
     21 
     22 #include "extract-store-integer.h"
     23 #include "nat/gdb_ptrace.h"
     24 #include "inf-ptrace.h"
     25 #include "gdbarch.h"
     26 
     27 /* Fetch register REGNUM from the inferior.  */
     28 
     29 void
     30 linux_nat_trad_target::fetch_register (struct regcache *regcache, int regnum)
     31 {
     32   struct gdbarch *gdbarch = regcache->arch ();
     33   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
     34   CORE_ADDR addr;
     35   gdb_byte *buf;
     36   size_t size;
     37   pid_t pid;
     38   int i;
     39 
     40   /* This isn't really an address, but ptrace thinks of it as one.  */
     41   addr = register_u_offset (gdbarch, regnum, 0);
     42   if (addr == (CORE_ADDR)-1
     43       || gdbarch_cannot_fetch_register (gdbarch, regnum))
     44     {
     45       regcache->raw_supply (regnum, NULL);
     46       return;
     47     }
     48 
     49   pid = get_ptrace_pid (regcache->ptid ());
     50 
     51   size = register_size (gdbarch, regnum);
     52   buf = (gdb_byte *) alloca (size);
     53 
     54   /* Read the register contents from the inferior a chunk at a time.  */
     55   for (i = 0; i < size; i += sizeof (PTRACE_TYPE_RET))
     56     {
     57       size_t chunk = std::min (sizeof (PTRACE_TYPE_RET), size - i);
     58       PTRACE_TYPE_RET val;
     59 
     60       errno = 0;
     61       val = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3) (uintptr_t) addr, 0);
     62       if (errno != 0)
     63 	error (_("Couldn't read register %s (#%d): %s."),
     64 	       gdbarch_register_name (gdbarch, regnum),
     65 	       regnum, safe_strerror (errno));
     66       store_unsigned_integer (buf + i, chunk, byte_order, val);
     67 
     68       addr += sizeof (PTRACE_TYPE_RET);
     69     }
     70   regcache->raw_supply (regnum, buf);
     71 }
     72 
     73 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
     74    for all registers.  */
     75 
     76 void
     77 linux_nat_trad_target::fetch_registers (struct regcache *regcache, int regnum)
     78 {
     79   if (regnum == -1)
     80     for (regnum = 0;
     81 	 regnum < gdbarch_num_regs (regcache->arch ());
     82 	 regnum++)
     83       fetch_register (regcache, regnum);
     84   else
     85     fetch_register (regcache, regnum);
     86 }
     87 
     88 /* Store register REGNUM into the inferior.  */
     89 
     90 void
     91 linux_nat_trad_target::store_register (const struct regcache *regcache,
     92 				       int regnum)
     93 {
     94   struct gdbarch *gdbarch = regcache->arch ();
     95   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
     96   CORE_ADDR addr;
     97   size_t size;
     98   gdb_byte *buf;
     99   pid_t pid;
    100   int i;
    101 
    102   /* This isn't really an address, but ptrace thinks of it as one.  */
    103   addr = register_u_offset (gdbarch, regnum, 1);
    104   if (addr == (CORE_ADDR)-1
    105       || gdbarch_cannot_store_register (gdbarch, regnum))
    106     return;
    107 
    108   pid = get_ptrace_pid (regcache->ptid ());
    109 
    110   size = register_size (gdbarch, regnum);
    111   buf = (gdb_byte *) alloca (size);
    112 
    113   /* Write the register contents into the inferior a chunk at a time.  */
    114   regcache->raw_collect (regnum, buf);
    115   for (i = 0; i < size; i += sizeof (PTRACE_TYPE_RET))
    116     {
    117       size_t chunk = std::min (sizeof (PTRACE_TYPE_RET), size - i);
    118       PTRACE_TYPE_RET val;
    119 
    120       val = extract_unsigned_integer (buf + i, chunk, byte_order);
    121       errno = 0;
    122       ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3) (uintptr_t) addr, val);
    123       if (errno != 0)
    124 	error (_("Couldn't write register %s (#%d): %s."),
    125 	       gdbarch_register_name (gdbarch, regnum),
    126 	       regnum, safe_strerror (errno));
    127 
    128       addr += sizeof (PTRACE_TYPE_RET);
    129     }
    130 }
    131 
    132 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
    133    this for all registers.  */
    134 
    135 void
    136 linux_nat_trad_target::store_registers (struct regcache *regcache, int regnum)
    137 {
    138   if (regnum == -1)
    139     for (regnum = 0;
    140 	 regnum < gdbarch_num_regs (regcache->arch ());
    141 	 regnum++)
    142       store_register (regcache, regnum);
    143   else
    144     store_register (regcache, regnum);
    145 }
    146