Commit | Line | Data |
---|---|---|
6b16acab MK |
1 | /* Native-dependent code for Solaris x86. |
2 | ||
42a4f53d | 3 | Copyright (C) 1988-2019 Free Software Foundation, Inc. |
6b16acab MK |
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 | |
a9762ec7 | 9 | the Free Software Foundation; either version 3 of the License, or |
6b16acab MK |
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 | |
a9762ec7 | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
6b16acab MK |
19 | |
20 | #include "defs.h" | |
21 | #include "regcache.h" | |
22 | ||
8674be79 | 23 | #include <sys/reg.h> |
6b16acab MK |
24 | #include <sys/procfs.h> |
25 | #include "gregset.h" | |
d1a7880c PA |
26 | #include "target.h" |
27 | #include "procfs.h" | |
6b16acab MK |
28 | |
29 | /* This file provids the (temporary) glue between the Solaris x86 | |
30 | target dependent code and the machine independent SVR4 /proc | |
31 | support. */ | |
32 | ||
33 | /* Solaris 10 (Solaris 2.10, SunOS 5.10) and up support two process | |
34 | data models, the traditional 32-bit data model (ILP32) and the | |
35 | 64-bit data model (LP64). The format of /proc depends on the data | |
36 | model of the observer (the controlling process, GDB in our case). | |
37 | The Solaris header files conveniently define PR_MODEL_NATIVE to the | |
38 | data model of the controlling process. If its value is | |
39 | PR_MODEL_LP64, we know that GDB is being compiled as a 64-bit | |
40 | program. | |
41 | ||
42 | Note that a 32-bit GDB won't be able to debug a 64-bit target | |
43 | process using /proc on Solaris. */ | |
44 | ||
8674be79 | 45 | #if PR_MODEL_NATIVE == PR_MODEL_LP64 |
6b16acab MK |
46 | |
47 | #include "amd64-nat.h" | |
48 | #include "amd64-tdep.h" | |
49 | ||
0bbc026e JM |
50 | /* Mapping between the general-purpose registers in gregset_t format |
51 | and GDB's register cache layout. */ | |
52 | ||
53 | /* From <sys/regset.h>. */ | |
54 | static int amd64_sol2_gregset64_reg_offset[] = { | |
55 | 14 * 8, /* %rax */ | |
56 | 11 * 8, /* %rbx */ | |
57 | 13 * 8, /* %rcx */ | |
58 | 12 * 8, /* %rdx */ | |
59 | 9 * 8, /* %rsi */ | |
60 | 8 * 8, /* %rdi */ | |
61 | 10 * 8, /* %rbp */ | |
62 | 20 * 8, /* %rsp */ | |
1777feb0 | 63 | 7 * 8, /* %r8 ... */ |
0bbc026e JM |
64 | 6 * 8, |
65 | 5 * 8, | |
66 | 4 * 8, | |
67 | 3 * 8, | |
68 | 2 * 8, | |
69 | 1 * 8, | |
70 | 0 * 8, /* ... %r15 */ | |
71 | 17 * 8, /* %rip */ | |
c71bb1cf | 72 | 19 * 8, /* %eflags */ |
0bbc026e JM |
73 | 18 * 8, /* %cs */ |
74 | 21 * 8, /* %ss */ | |
75 | 25 * 8, /* %ds */ | |
76 | 24 * 8, /* %es */ | |
77 | 22 * 8, /* %fs */ | |
78 | 23 * 8 /* %gs */ | |
79 | }; | |
80 | ||
81 | /* 32-bit registers are provided by Solaris in 64-bit format, so just | |
82 | give a subset of the list above. */ | |
83 | static int amd64_sol2_gregset32_reg_offset[] = { | |
84 | 14 * 8, /* %eax */ | |
85 | 13 * 8, /* %ecx */ | |
86 | 12 * 8, /* %edx */ | |
87 | 11 * 8, /* %ebx */ | |
88 | 20 * 8, /* %esp */ | |
89 | 10 * 8, /* %ebp */ | |
90 | 9 * 8, /* %esi */ | |
91 | 8 * 8, /* %edi */ | |
92 | 17 * 8, /* %eip */ | |
c71bb1cf | 93 | 19 * 8, /* %eflags */ |
0bbc026e JM |
94 | 18 * 8, /* %cs */ |
95 | 21 * 8, /* %ss */ | |
96 | 25 * 8, /* %ds */ | |
97 | 24 * 8, /* %es */ | |
98 | 22 * 8, /* %fs */ | |
99 | 23 * 8 /* %gs */ | |
100 | }; | |
101 | ||
6b16acab | 102 | void |
7f7fe91e | 103 | supply_gregset (struct regcache *regcache, const prgregset_t *gregs) |
6b16acab | 104 | { |
7f7fe91e | 105 | amd64_supply_native_gregset (regcache, gregs, -1); |
6b16acab MK |
106 | } |
107 | ||
108 | void | |
7f7fe91e | 109 | supply_fpregset (struct regcache *regcache, const prfpregset_t *fpregs) |
6b16acab | 110 | { |
7f7fe91e | 111 | amd64_supply_fxsave (regcache, -1, fpregs); |
6b16acab MK |
112 | } |
113 | ||
114 | void | |
7f7fe91e UW |
115 | fill_gregset (const struct regcache *regcache, |
116 | prgregset_t *gregs, int regnum) | |
6b16acab | 117 | { |
7f7fe91e | 118 | amd64_collect_native_gregset (regcache, gregs, regnum); |
6b16acab MK |
119 | } |
120 | ||
121 | void | |
7f7fe91e UW |
122 | fill_fpregset (const struct regcache *regcache, |
123 | prfpregset_t *fpregs, int regnum) | |
6b16acab | 124 | { |
7f7fe91e | 125 | amd64_collect_fxsave (regcache, regnum, fpregs); |
6b16acab MK |
126 | } |
127 | ||
8674be79 RO |
128 | #else /* PR_MODEL_NATIVE != PR_MODEL_LP64 */ |
129 | ||
130 | #include "i386-tdep.h" | |
131 | #include "i387-tdep.h" | |
132 | ||
133 | /* The `/proc' interface divides the target machine's register set up | |
134 | into two different sets, the general purpose register set (gregset) | |
135 | and the floating-point register set (fpregset). | |
136 | ||
137 | The actual structure is, of course, naturally machine dependent, and is | |
138 | different for each set of registers. For the i386 for example, the | |
139 | general-purpose register set is typically defined by: | |
140 | ||
141 | typedef int gregset_t[19]; (in <sys/regset.h>) | |
142 | ||
143 | #define GS 0 (in <sys/reg.h>) | |
144 | #define FS 1 | |
145 | ... | |
146 | #define UESP 17 | |
147 | #define SS 18 | |
148 | ||
149 | and the floating-point set by: | |
150 | ||
151 | typedef struct fpregset { | |
152 | union { | |
153 | struct fpchip_state // fp extension state // | |
154 | { | |
155 | int state[27]; // 287/387 saved state // | |
156 | int status; // status word saved at // | |
157 | // exception // | |
158 | } fpchip_state; | |
159 | struct fp_emul_space // for emulators // | |
160 | { | |
161 | char fp_emul[246]; | |
162 | char fp_epad[2]; | |
163 | } fp_emul_space; | |
164 | int f_fpregs[62]; // union of the above // | |
165 | } fp_reg_set; | |
166 | long f_wregs[33]; // saved weitek state // | |
167 | } fpregset_t; | |
168 | ||
169 | Incidentally fpchip_state contains the FPU state in the same format | |
170 | as used by the "fsave" instruction, and that's the only thing we | |
171 | support here. I don't know how the emulator stores it state. The | |
172 | Weitek stuff definitely isn't supported. | |
173 | ||
174 | The routines defined here, provide the packing and unpacking of | |
175 | gregset_t and fpregset_t formatted data. */ | |
176 | ||
177 | /* Mapping between the general-purpose registers in `/proc' | |
178 | format and GDB's register array layout. */ | |
179 | static int regmap[] = | |
180 | { | |
181 | EAX, ECX, EDX, EBX, | |
182 | UESP, EBP, ESI, EDI, | |
183 | EIP, EFL, CS, SS, | |
184 | DS, ES, FS, GS | |
185 | }; | |
186 | ||
187 | /* Fill GDB's register array with the general-purpose register values | |
188 | in *GREGSETP. */ | |
189 | ||
190 | void | |
191 | supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) | |
192 | { | |
193 | const greg_t *regp = (const greg_t *) gregsetp; | |
194 | int regnum; | |
195 | ||
196 | for (regnum = 0; regnum < I386_NUM_GREGS; regnum++) | |
197 | regcache->raw_supply (regnum, regp + regmap[regnum]); | |
198 | } | |
199 | ||
200 | /* Fill register REGNUM (if it is a general-purpose register) in | |
201 | *GREGSETPS with the value in GDB's register array. If REGNUM is -1, | |
202 | do this for all registers. */ | |
6b16acab | 203 | |
8674be79 RO |
204 | void |
205 | fill_gregset (const struct regcache *regcache, | |
206 | gregset_t *gregsetp, int regnum) | |
207 | { | |
208 | greg_t *regp = (greg_t *) gregsetp; | |
209 | int i; | |
210 | ||
211 | for (i = 0; i < I386_NUM_GREGS; i++) | |
212 | if (regnum == -1 || regnum == i) | |
213 | regcache->raw_collect (i, regp + regmap[i]); | |
214 | } | |
215 | ||
216 | /* Fill GDB's register array with the floating-point register values in | |
217 | *FPREGSETP. */ | |
218 | ||
219 | void | |
220 | supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) | |
221 | { | |
222 | if (gdbarch_fp0_regnum (regcache->arch ()) == 0) | |
223 | return; | |
224 | ||
225 | i387_supply_fsave (regcache, -1, fpregsetp); | |
226 | } | |
227 | ||
228 | /* Fill register REGNO (if it is a floating-point register) in | |
229 | *FPREGSETP with the value in GDB's register array. If REGNO is -1, | |
230 | do this for all registers. */ | |
231 | ||
232 | void | |
233 | fill_fpregset (const struct regcache *regcache, | |
234 | fpregset_t *fpregsetp, int regno) | |
235 | { | |
236 | if (gdbarch_fp0_regnum (regcache->arch ()) == 0) | |
237 | return; | |
238 | ||
239 | i387_collect_fsave (regcache, regno, fpregsetp); | |
240 | } | |
6b16acab MK |
241 | |
242 | #endif | |
0bbc026e | 243 | |
0bbc026e JM |
244 | void |
245 | _initialize_amd64_sol2_nat (void) | |
246 | { | |
8674be79 | 247 | #if PR_MODEL_NATIVE == PR_MODEL_LP64 |
0bbc026e JM |
248 | amd64_native_gregset32_reg_offset = amd64_sol2_gregset32_reg_offset; |
249 | amd64_native_gregset32_num_regs = | |
250 | ARRAY_SIZE (amd64_sol2_gregset32_reg_offset); | |
251 | amd64_native_gregset64_reg_offset = amd64_sol2_gregset64_reg_offset; | |
252 | amd64_native_gregset64_num_regs = | |
253 | ARRAY_SIZE (amd64_sol2_gregset64_reg_offset); | |
254 | #endif | |
255 | } |