Commit | Line | Data |
---|---|---|
9bebe500 SS |
1 | /* Native-dependent code for Motorola 680x0 running LynxOS. |
2 | Copyright 1986, 1987, 1989, 1991, 1993 Free Software Foundation, Inc. | |
25286543 SG |
3 | |
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | ||
20 | #include "defs.h" | |
21 | #include "frame.h" | |
22 | #include "inferior.h" | |
9bebe500 | 23 | #include "gdbcore.h" |
25286543 SG |
24 | #include "target.h" |
25 | ||
9bebe500 SS |
26 | #include <sys/param.h> |
27 | #include <sys/dir.h> | |
28 | #include <signal.h> | |
29 | #include <sys/types.h> | |
30 | #include <itimer.h> | |
31 | #include <mem.h> | |
32 | #include <sys/time.h> | |
33 | #include <resource.h> | |
34 | #include <sys/ioctl.h> | |
35 | #include <fcntl.h> | |
36 | #include <sys/file.h> | |
37 | #include <sys/stat.h> | |
25286543 | 38 | #include <sys/ptrace.h> |
9bebe500 SS |
39 | #include <kernel.h> |
40 | #include <conf.h> | |
41 | #include <proc.h> | |
42 | #include <errno.h> | |
25286543 SG |
43 | |
44 | /* Return the address in the core dump or inferior of register REGNO. | |
9bebe500 | 45 | BLOCKEND is the address of the end of the user structure. */ |
25286543 SG |
46 | |
47 | static unsigned int | |
9bebe500 SS |
48 | core_register_addr (regno, blockend) |
49 | unsigned int regno, blockend; | |
50 | { | |
51 | struct st_entry s; | |
52 | unsigned int offset; | |
53 | ||
54 | if (regno >= 0 && regno <= FP_REGNUM) | |
55 | offset = (char *) &s.ec.regs[regno] - (char *) &s; | |
56 | else if (regno == SP_REGNUM) | |
57 | offset = (char *) &s.stackp - (char *) &s; | |
58 | else if (regno == PS_REGNUM) | |
59 | offset = (char *) &s.ec.status - (char *) &s; | |
60 | else if (regno == PC_REGNUM) | |
61 | offset = (char *) &s.ec.pc - (char *) &s; | |
62 | else if (regno >= FP0_REGNUM && regno <= (FPC_REGNUM - 1)) | |
63 | offset = (char *) &s.ec.fregs[(regno - FP0_REGNUM) * 3] - (char *) &s; | |
64 | else if (regno >= FPC_REGNUM && regno <= FPI_REGNUM) | |
65 | offset = (char *) &s.ec.fcregs[regno - FPC_REGNUM] - (char *) &s; | |
66 | ||
67 | return blockend + offset; | |
68 | } | |
69 | ||
70 | unsigned int | |
25286543 SG |
71 | register_addr (regno, blockend) |
72 | int regno, blockend; | |
73 | { | |
9bebe500 SS |
74 | struct st_entry s; |
75 | unsigned int offset; | |
76 | ||
77 | if (regno >= 0 && regno <= FP_REGNUM) | |
78 | offset = (char *) &s.ec.regs[regno] - (char *) &s.ec; | |
79 | else if (regno == SP_REGNUM) | |
80 | offset = (char *) &s.stackp - (char *) &s; | |
81 | else if (regno == PS_REGNUM) | |
82 | offset = (char *) &s.ec.status - (char *) &s.ec; | |
83 | else if (regno == PC_REGNUM) | |
84 | offset = (char *) &s.ec.pc - (char *) &s.ec; | |
85 | else if (regno >= FP0_REGNUM && regno <= (FPC_REGNUM - 1)) | |
86 | offset = (char *) &s.ec.fregs[(regno - FP0_REGNUM) * 3] - (char *) &s.ec; | |
87 | else if (regno >= FPC_REGNUM && regno <= FPI_REGNUM) | |
88 | offset = (char *) &s.ec.fcregs[regno - FPC_REGNUM] - (char *) &s.ec; | |
89 | ||
90 | return blockend + offset; | |
25286543 SG |
91 | } |
92 | ||
9bebe500 SS |
93 | #ifdef FETCH_INFERIOR_REGISTERS |
94 | ||
95 | /* Fetch one register. */ | |
25286543 SG |
96 | |
97 | static void | |
98 | fetch_register (regno, offset, bpid) | |
99 | int regno, bpid; | |
100 | unsigned int offset; | |
101 | { | |
9bebe500 SS |
102 | char buf[MAX_REGISTER_RAW_SIZE], mess[128]; |
103 | unsigned int regaddr, i, ptrace_request; | |
25286543 | 104 | |
9bebe500 | 105 | ptrace_request = regno != SP_REGNUM ? PTRACE_PEEKDATA : PTRACE_PEEKUSP; |
25286543 SG |
106 | regaddr = register_addr (regno, offset); |
107 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) | |
108 | { | |
109 | errno = 0; | |
9bebe500 | 110 | *(int *) &buf[i] = ptrace (ptrace_request, bpid, |
25286543 | 111 | (PTRACE_ARG3_TYPE) regaddr, 0); |
25286543 | 112 | if (errno != 0) |
9bebe500 | 113 | { |
25286543 SG |
114 | sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno); |
115 | perror_with_name (mess); | |
9bebe500 SS |
116 | } |
117 | regaddr += sizeof (int); | |
25286543 SG |
118 | } |
119 | supply_register (regno, buf); | |
120 | } | |
121 | ||
25286543 SG |
122 | static void |
123 | store_register (regno, offset, bpid) | |
124 | int regno, bpid; | |
125 | unsigned int offset; | |
126 | { | |
9bebe500 | 127 | unsigned int i, regaddr, ptrace_request; |
25286543 | 128 | char mess[128]; |
25286543 | 129 | |
9bebe500 | 130 | ptrace_request = regno != SP_REGNUM ? PTRACE_POKEUSER : PTRACE_POKEUSP; |
25286543 | 131 | regaddr = register_addr (regno, offset); |
9bebe500 | 132 | for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int)) |
25286543 SG |
133 | { |
134 | errno = 0; | |
9bebe500 | 135 | ptrace (ptrace_request, bpid, (PTRACE_ARG3_TYPE) regaddr, |
25286543 SG |
136 | *(int *) ®isters[REGISTER_BYTE (regno) + i]); |
137 | if (errno != 0) | |
9bebe500 SS |
138 | { |
139 | sprintf (mess, "writing register %s (#%d)", reg_names[regno], regno); | |
25286543 SG |
140 | perror_with_name (mess); |
141 | } | |
9bebe500 | 142 | regaddr += sizeof (int); |
25286543 SG |
143 | } |
144 | } | |
145 | ||
25286543 | 146 | static unsigned int |
9bebe500 SS |
147 | fetch_offset (pid, write) |
148 | int pid, write; | |
25286543 SG |
149 | { |
150 | struct st_entry s; | |
151 | unsigned int specpage_off, offset = (char *) &s.ecp - (char *) &s; | |
152 | ||
9bebe500 SS |
153 | if (write) |
154 | { | |
155 | errno = 0; | |
156 | specpage_off = ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE) 0, 0); | |
157 | if (errno != 0) | |
158 | perror_with_name ("ptrace"); | |
159 | errno = 0; | |
160 | offset = ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) offset, 0) | |
161 | - specpage_off; | |
162 | if (errno != 0) | |
163 | perror_with_name ("ptrace"); | |
164 | } | |
165 | else | |
166 | { | |
167 | errno = 0; | |
168 | offset = ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) offset, 0); | |
169 | if (errno != 0) | |
170 | perror_with_name ("ptrace"); | |
171 | } | |
25286543 SG |
172 | return offset; |
173 | } | |
174 | ||
25286543 SG |
175 | void |
176 | fetch_inferior_registers (regno) | |
177 | int regno; | |
178 | { | |
9bebe500 SS |
179 | unsigned int offset = fetch_offset (inferior_pid, 0); |
180 | ||
25286543 SG |
181 | if (regno == -1) |
182 | { | |
183 | for (regno = 0; regno < NUM_REGS; regno++) | |
9bebe500 | 184 | fetch_register (regno, offset, inferior_pid); |
25286543 | 185 | } |
9bebe500 | 186 | else |
25286543 SG |
187 | fetch_register (regno, offset, inferior_pid); |
188 | } | |
189 | ||
25286543 SG |
190 | void |
191 | store_inferior_registers (regno) | |
192 | int regno; | |
193 | { | |
9bebe500 | 194 | unsigned int offset = fetch_offset (inferior_pid, 1); |
25286543 SG |
195 | |
196 | if (regno == -1) | |
197 | { | |
9bebe500 | 198 | for (regno = 0; regno < NUM_REGS; regno++) |
25286543 SG |
199 | store_register (regno, offset, inferior_pid); |
200 | } | |
201 | else | |
202 | store_register (regno, offset, inferior_pid); | |
203 | } | |
204 | ||
9bebe500 SS |
205 | void |
206 | fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) | |
207 | char *core_reg_sect; | |
208 | unsigned core_reg_size; | |
209 | int which; | |
210 | unsigned int reg_addr; /* Unused in this version */ | |
211 | { | |
212 | unsigned int regno; | |
213 | ||
214 | for (regno = 0; regno < NUM_REGS; regno++) | |
215 | { | |
216 | unsigned int addr; | |
217 | ||
218 | addr = core_register_addr (regno, (unsigned) 0); | |
219 | supply_register (regno, core_reg_sect + addr); | |
220 | } | |
221 | } | |
222 | #endif /* FETCH_INFERIOR_REGISTERS */ | |
223 | ||
25286543 SG |
224 | /* Wait for child to do something. Return pid of child, or -1 in case |
225 | of error; store status through argument pointer STATUS. */ | |
226 | ||
227 | int | |
de43d7d0 SG |
228 | child_wait (pid, status) |
229 | int pid; | |
25286543 SG |
230 | int *status; |
231 | { | |
25286543 SG |
232 | int save_errno; |
233 | int thread; | |
234 | ||
235 | while (1) | |
236 | { | |
237 | int sig; | |
238 | ||
239 | if (attach_flag) | |
240 | set_sigint_trap(); /* Causes SIGINT to be passed on to the | |
241 | attached process. */ | |
242 | pid = wait (status); | |
243 | save_errno = errno; | |
244 | ||
245 | if (attach_flag) | |
246 | clear_sigint_trap(); | |
247 | ||
248 | if (pid == -1) | |
249 | { | |
250 | if (save_errno == EINTR) | |
251 | continue; | |
252 | fprintf (stderr, "Child process unexpectedly missing: %s.\n", | |
253 | safe_strerror (save_errno)); | |
254 | *status = 42; /* Claim it exited with signal 42 */ | |
255 | return -1; | |
256 | } | |
257 | ||
258 | if (pid != PIDGET (inferior_pid)) /* Some other process?!? */ | |
259 | continue; | |
260 | ||
261 | /* thread = WIFTID (*status);*/ | |
262 | thread = *status >> 16; | |
263 | ||
264 | /* Initial thread value can only be acquired via wait, so we have to | |
265 | resort to this hack. */ | |
266 | ||
267 | if (TIDGET (inferior_pid) == 0) | |
268 | { | |
269 | inferior_pid = BUILDPID (inferior_pid, thread); | |
270 | add_thread (inferior_pid); | |
271 | } | |
272 | ||
273 | pid = BUILDPID (pid, thread); | |
274 | ||
275 | return pid; | |
276 | } | |
277 | } |