48e52d2a7c285982e21d668b43f8768b585a2df0
[deliverable/binutils-gdb.git] / gdb / lynx-nat.c
1 /* Native-dependent code for LynxOS.
2 Copyright 1993, 1994 Free Software Foundation, Inc.
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"
23 #include "target.h"
24
25 #include <sys/ptrace.h>
26 #include <sys/wait.h>
27
28 static unsigned long registers_addr PARAMS ((int pid));
29
30 #define X(ENTRY)(offsetof(struct econtext, ENTRY))
31
32 #ifdef I386
33 /* Mappings from tm-i386v.h */
34
35 static int regmap[] =
36 {
37 X(eax),
38 X(ecx),
39 X(edx),
40 X(ebx),
41 X(esp), /* sp */
42 X(ebp), /* fp */
43 X(esi),
44 X(edi),
45 X(eip), /* pc */
46 X(flags), /* ps */
47 X(cs),
48 X(ss),
49 X(ds),
50 X(es),
51 X(ecode), /* Lynx doesn't give us either fs or gs, so */
52 X(fault), /* we just substitute these two in the hopes
53 that they are useful. */
54 };
55 #endif
56
57 #ifdef M68K
58 /* Mappings from tm-m68k.h */
59
60 static int regmap[] =
61 {
62 X(regs[0]), /* d0 */
63 X(regs[1]), /* d1 */
64 X(regs[2]), /* d2 */
65 X(regs[3]), /* d3 */
66 X(regs[4]), /* d4 */
67 X(regs[5]), /* d5 */
68 X(regs[6]), /* d6 */
69 X(regs[7]), /* d7 */
70 X(regs[8]), /* a0 */
71 X(regs[9]), /* a1 */
72 X(regs[10]), /* a2 */
73 X(regs[11]), /* a3 */
74 X(regs[12]), /* a4 */
75 X(regs[13]), /* a5 */
76 X(regs[14]), /* fp */
77 offsetof (st_t, usp) - offsetof (st_t, ec), /* sp */
78 X(status), /* ps */
79 X(pc),
80
81 X(fregs[0*3]), /* fp0 */
82 X(fregs[1*3]), /* fp1 */
83 X(fregs[2*3]), /* fp2 */
84 X(fregs[3*3]), /* fp3 */
85 X(fregs[4*3]), /* fp4 */
86 X(fregs[5*3]), /* fp5 */
87 X(fregs[6*3]), /* fp6 */
88 X(fregs[7*3]), /* fp7 */
89
90 X(fcregs[0]), /* fpcontrol */
91 X(fcregs[1]), /* fpstatus */
92 X(fcregs[2]), /* fpiaddr */
93 X(ssw), /* fpcode */
94 X(fault), /* fpflags */
95 };
96 #endif
97
98 /* Return the offset relative to the start of the per-thread data to the
99 saved context block. */
100
101 static unsigned long
102 registers_addr(pid)
103 int pid;
104 {
105 CORE_ADDR stblock;
106 int ecpoff = offsetof(st_t, ecp);
107 CORE_ADDR ecp;
108
109 errno = 0;
110 stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE)0,
111 0);
112 if (errno)
113 perror_with_name ("registers_addr(PTRACE_THREADUSER)");
114
115 ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE)ecpoff,
116 0);
117 if (errno)
118 perror_with_name ("registers_addr(PTRACE_PEEKTHREAD)");
119
120 return ecp - stblock;
121 }
122
123 /* Fetch one or more registers from the inferior. REGNO == -1 to get
124 them all. We actually fetch more than requested, when convenient,
125 marking them as valid so we won't fetch them again. */
126
127 void
128 fetch_inferior_registers (regno)
129 int regno;
130 {
131 int reglo, reghi;
132 int i;
133 unsigned long ecp;
134
135 if (regno == -1)
136 {
137 reglo = 0;
138 reghi = NUM_REGS - 1;
139 }
140 else
141 reglo = reghi = regno;
142
143 ecp = registers_addr (inferior_pid);
144
145 for (regno = reglo; regno <= reghi; regno++)
146 {
147 char buf[MAX_REGISTER_RAW_SIZE];
148 int ptrace_fun = PTRACE_PEEKTHREAD;
149
150 #ifdef PTRACE_PEEKUSP
151 ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
152 #endif
153
154 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
155 {
156 unsigned int reg;
157
158 errno = 0;
159 reg = ptrace (ptrace_fun, inferior_pid,
160 (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), 0);
161 if (errno)
162 perror_with_name ("fetch_inferior_registers(ptrace)");
163
164 *(int *)&buf[i] = reg;
165 }
166 supply_register (regno, buf);
167 }
168 }
169
170 /* Store our register values back into the inferior.
171 If REGNO is -1, do this for all registers.
172 Otherwise, REGNO specifies which register (so we can save time). */
173
174 void
175 store_inferior_registers (regno)
176 int regno;
177 {
178 int reglo, reghi;
179 int i;
180 unsigned long ecp;
181
182 if (regno == -1)
183 {
184 reglo = 0;
185 reghi = NUM_REGS - 1;
186 }
187 else
188 reglo = reghi = regno;
189
190 ecp = registers_addr (inferior_pid);
191
192 for (regno = reglo; regno <= reghi; regno++)
193 {
194 int ptrace_fun = PTRACE_POKEUSER;
195
196 #ifdef PTRACE_POKEUSP
197 ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
198 #endif
199
200 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
201 {
202 unsigned int reg;
203
204 reg = *(unsigned int *)&registers[REGISTER_BYTE (regno) + i];
205
206 errno = 0;
207 ptrace (ptrace_fun, inferior_pid,
208 (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), reg);
209 if (errno)
210 perror_with_name ("PTRACE_POKEUSER");
211 }
212 }
213 }
214
215 /* Wait for child to do something. Return pid of child, or -1 in case
216 of error; store status through argument pointer OURSTATUS. */
217
218 int
219 child_wait (pid, ourstatus)
220 int pid;
221 struct target_waitstatus *ourstatus;
222 {
223 int save_errno;
224 int thread;
225 int status;
226
227 while (1)
228 {
229 int sig;
230
231 if (attach_flag)
232 set_sigint_trap(); /* Causes SIGINT to be passed on to the
233 attached process. */
234 pid = wait (status);
235 save_errno = errno;
236
237 if (attach_flag)
238 clear_sigint_trap();
239
240 if (pid == -1)
241 {
242 if (save_errno == EINTR)
243 continue;
244 fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
245 safe_strerror (save_errno));
246 /* Claim it exited with unknown signal. */
247 ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
248 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
249 return -1;
250 }
251
252 if (pid != PIDGET (inferior_pid)) /* Some other process?!? */
253 continue;
254
255 /* thread = WIFTID (status);*/
256 thread = status >> 16;
257
258 /* Initial thread value can only be acquired via wait, so we have to
259 resort to this hack. */
260
261 if (TIDGET (inferior_pid) == 0)
262 {
263 inferior_pid = BUILDPID (inferior_pid, thread);
264 add_thread (inferior_pid);
265 }
266
267 pid = BUILDPID (pid, thread);
268
269 store_waitstatus (ourstatus, status);
270
271 return pid;
272 }
273 }
274
275 /* Convert a Lynx process ID to a string. Returns the string in a static
276 buffer. */
277
278 char *
279 lynx_pid_to_str (pid)
280 int pid;
281 {
282 static char buf[40];
283
284 sprintf (buf, "process %d thread %d", PIDGET (pid), TIDGET (pid));
285
286 return buf;
287 }
288
289 /* Extract the register values out of the core file and store
290 them where `read_register' will find them.
291
292 CORE_REG_SECT points to the register values themselves, read into memory.
293 CORE_REG_SIZE is the size of that area.
294 WHICH says which set of registers we are handling (0 = int, 2 = float
295 on machines where they are discontiguous).
296 REG_ADDR is the offset from u.u_ar0 to the register values relative to
297 core_reg_sect. This is used with old-fashioned core files to
298 locate the registers in a large upage-plus-stack ".reg" section.
299 Original upage address X is at location core_reg_sect+x+reg_addr.
300 */
301
302 void
303 fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
304 char *core_reg_sect;
305 unsigned core_reg_size;
306 int which;
307 unsigned reg_addr;
308 {
309 struct st_entry s;
310 unsigned int regno;
311
312 for (regno = 0; regno < NUM_REGS; regno++)
313 supply_register (regno, core_reg_sect + offsetof (st_t, ec)
314 + regmap[regno]);
315 }
This page took 0.035898 seconds and 3 git commands to generate.