Convert struct target_ops to C++
[external/binutils.git] / gdb / linux-nat-trad.c
1 /* Generic GNU/Linux target using traditional ptrace register access.
2
3    Copyright (C) 1988-2018 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 "defs.h"
21 #include "linux-nat-trad.h"
22
23 #include "nat/gdb_ptrace.h"
24 #include "inf-ptrace.h"
25
26 /* Fetch register REGNUM from the inferior.  */
27
28 void
29 linux_nat_trad_target::fetch_register (struct regcache *regcache, int regnum)
30 {
31   struct gdbarch *gdbarch = regcache->arch ();
32   CORE_ADDR addr;
33   size_t size;
34   PTRACE_TYPE_RET *buf;
35   pid_t pid;
36   int i;
37
38   /* This isn't really an address, but ptrace thinks of it as one.  */
39   addr = register_u_offset (gdbarch, regnum, 0);
40   if (addr == (CORE_ADDR)-1
41       || gdbarch_cannot_fetch_register (gdbarch, regnum))
42     {
43       regcache_raw_supply (regcache, regnum, NULL);
44       return;
45     }
46
47   pid = get_ptrace_pid (regcache_get_ptid (regcache));
48
49   size = register_size (gdbarch, regnum);
50   gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
51   buf = (PTRACE_TYPE_RET *) alloca (size);
52
53   /* Read the register contents from the inferior a chunk at a time.  */
54   for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
55     {
56       errno = 0;
57       buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)(uintptr_t)addr, 0);
58       if (errno != 0)
59         error (_("Couldn't read register %s (#%d): %s."),
60                gdbarch_register_name (gdbarch, regnum),
61                regnum, safe_strerror (errno));
62
63       addr += sizeof (PTRACE_TYPE_RET);
64     }
65   regcache_raw_supply (regcache, regnum, buf);
66 }
67
68 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
69    for all registers.  */
70
71 void
72 linux_nat_trad_target::fetch_registers (struct regcache *regcache, int regnum)
73 {
74   if (regnum == -1)
75     for (regnum = 0;
76          regnum < gdbarch_num_regs (regcache->arch ());
77          regnum++)
78       fetch_register (regcache, regnum);
79   else
80     fetch_register (regcache, regnum);
81 }
82
83 /* Store register REGNUM into the inferior.  */
84
85 void
86 linux_nat_trad_target::store_register (const struct regcache *regcache,
87                                        int regnum)
88 {
89   struct gdbarch *gdbarch = regcache->arch ();
90   CORE_ADDR addr;
91   size_t size;
92   PTRACE_TYPE_RET *buf;
93   pid_t pid;
94   int i;
95
96   /* This isn't really an address, but ptrace thinks of it as one.  */
97   addr = register_u_offset (gdbarch, regnum, 1);
98   if (addr == (CORE_ADDR)-1
99       || gdbarch_cannot_store_register (gdbarch, regnum))
100     return;
101
102   pid = get_ptrace_pid (regcache_get_ptid (regcache));
103
104   size = register_size (gdbarch, regnum);
105   gdb_assert ((size % sizeof (PTRACE_TYPE_RET)) == 0);
106   buf = (PTRACE_TYPE_RET *) alloca (size);
107
108   /* Write the register contents into the inferior a chunk at a time.  */
109   regcache_raw_collect (regcache, regnum, buf);
110   for (i = 0; i < size / sizeof (PTRACE_TYPE_RET); i++)
111     {
112       errno = 0;
113       ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)(uintptr_t)addr, buf[i]);
114       if (errno != 0)
115         error (_("Couldn't write register %s (#%d): %s."),
116                gdbarch_register_name (gdbarch, regnum),
117                regnum, safe_strerror (errno));
118
119       addr += sizeof (PTRACE_TYPE_RET);
120     }
121 }
122
123 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
124    this for all registers.  */
125
126 void
127 linux_nat_trad_target::store_registers (struct regcache *regcache, int regnum)
128 {
129   if (regnum == -1)
130     for (regnum = 0;
131          regnum < gdbarch_num_regs (regcache->arch ());
132          regnum++)
133       store_register (regcache, regnum);
134   else
135     store_register (regcache, regnum);
136 }