Add Rust support to source highlighting
[external/binutils.git] / gdb / linux-nat-trad.c
1 /* Generic GNU/Linux target using traditional ptrace register access.
2
3    Copyright (C) 1988-2019 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 #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 }