*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / lynx-nat.c
CommitLineData
c906108c 1/* Native-dependent code for LynxOS.
2555fe1a 2
197e01b6 3 Copyright (C) 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2003 Free
2555fe1a 4 Software Foundation, Inc.
c906108c 5
c5aa993b 6 This file is part of GDB.
c906108c 7
c5aa993b
JM
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
c906108c 12
c5aa993b
JM
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
c906108c 17
c5aa993b
JM
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
197e01b6
EZ
20 Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
c906108c
SS
22
23#include "defs.h"
24#include "frame.h"
25#include "inferior.h"
26#include "target.h"
27#include "gdbcore.h"
4e052eda 28#include "regcache.h"
c906108c
SS
29
30#include <sys/ptrace.h>
2555fe1a 31#Include "gdb_wait.h"
c906108c
SS
32#include <sys/fpp.h>
33
a14ed312
KB
34static unsigned long registers_addr (int pid);
35static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
c906108c
SS
36
37#define X(ENTRY)(offsetof(struct econtext, ENTRY))
38
39#ifdef I386
40/* Mappings from tm-i386v.h */
41
42static int regmap[] =
43{
c5aa993b
JM
44 X (eax),
45 X (ecx),
46 X (edx),
47 X (ebx),
48 X (esp), /* sp */
49 X (ebp), /* fp */
50 X (esi),
51 X (edi),
52 X (eip), /* pc */
53 X (flags), /* ps */
54 X (cs),
55 X (ss),
56 X (ds),
57 X (es),
58 X (ecode), /* Lynx doesn't give us either fs or gs, so */
59 X (fault), /* we just substitute these two in the hopes
c906108c
SS
60 that they are useful. */
61};
62#endif /* I386 */
63
64#ifdef M68K
65/* Mappings from tm-m68k.h */
66
67static int regmap[] =
68{
c5aa993b
JM
69 X (regs[0]), /* d0 */
70 X (regs[1]), /* d1 */
71 X (regs[2]), /* d2 */
72 X (regs[3]), /* d3 */
73 X (regs[4]), /* d4 */
74 X (regs[5]), /* d5 */
75 X (regs[6]), /* d6 */
76 X (regs[7]), /* d7 */
77 X (regs[8]), /* a0 */
78 X (regs[9]), /* a1 */
79 X (regs[10]), /* a2 */
80 X (regs[11]), /* a3 */
81 X (regs[12]), /* a4 */
82 X (regs[13]), /* a5 */
83 X (regs[14]), /* fp */
84 offsetof (st_t, usp) - offsetof (st_t, ec), /* sp */
85 X (status), /* ps */
86 X (pc),
87
88 X (fregs[0 * 3]), /* fp0 */
89 X (fregs[1 * 3]), /* fp1 */
90 X (fregs[2 * 3]), /* fp2 */
91 X (fregs[3 * 3]), /* fp3 */
92 X (fregs[4 * 3]), /* fp4 */
93 X (fregs[5 * 3]), /* fp5 */
94 X (fregs[6 * 3]), /* fp6 */
95 X (fregs[7 * 3]), /* fp7 */
96
97 X (fcregs[0]), /* fpcontrol */
98 X (fcregs[1]), /* fpstatus */
99 X (fcregs[2]), /* fpiaddr */
100 X (ssw), /* fpcode */
101 X (fault), /* fpflags */
c906108c
SS
102};
103#endif /* M68K */
104
105#ifdef SPARC
106/* Mappings from tm-sparc.h */
107
108#define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
109
110static int regmap[] =
111{
112 -1, /* g0 */
c5aa993b
JM
113 X (g1),
114 X (g2),
115 X (g3),
116 X (g4),
c906108c
SS
117 -1, /* g5->g7 aren't saved by Lynx */
118 -1,
119 -1,
120
c5aa993b
JM
121 X (o[0]),
122 X (o[1]),
123 X (o[2]),
124 X (o[3]),
125 X (o[4]),
126 X (o[5]),
127 X (o[6]), /* sp */
128 X (o[7]), /* ra */
129
130 -1, -1, -1, -1, -1, -1, -1, -1, /* l0 -> l7 */
131
132 -1, -1, -1, -1, -1, -1, -1, -1, /* i0 -> i7 */
133
134 FX (f.fregs[0]), /* f0 */
135 FX (f.fregs[1]),
136 FX (f.fregs[2]),
137 FX (f.fregs[3]),
138 FX (f.fregs[4]),
139 FX (f.fregs[5]),
140 FX (f.fregs[6]),
141 FX (f.fregs[7]),
142 FX (f.fregs[8]),
143 FX (f.fregs[9]),
144 FX (f.fregs[10]),
145 FX (f.fregs[11]),
146 FX (f.fregs[12]),
147 FX (f.fregs[13]),
148 FX (f.fregs[14]),
149 FX (f.fregs[15]),
150 FX (f.fregs[16]),
151 FX (f.fregs[17]),
152 FX (f.fregs[18]),
153 FX (f.fregs[19]),
154 FX (f.fregs[20]),
155 FX (f.fregs[21]),
156 FX (f.fregs[22]),
157 FX (f.fregs[23]),
158 FX (f.fregs[24]),
159 FX (f.fregs[25]),
160 FX (f.fregs[26]),
161 FX (f.fregs[27]),
162 FX (f.fregs[28]),
163 FX (f.fregs[29]),
164 FX (f.fregs[30]),
165 FX (f.fregs[31]),
166
167 X (y),
168 X (psr),
169 X (wim),
170 X (tbr),
171 X (pc),
172 X (npc),
173 FX (fsr), /* fpsr */
c906108c
SS
174 -1, /* cpsr */
175};
176#endif /* SPARC */
177
178#ifdef rs6000
179
180static int regmap[] =
181{
c5aa993b
JM
182 X (iregs[0]), /* r0 */
183 X (iregs[1]),
184 X (iregs[2]),
185 X (iregs[3]),
186 X (iregs[4]),
187 X (iregs[5]),
188 X (iregs[6]),
189 X (iregs[7]),
190 X (iregs[8]),
191 X (iregs[9]),
192 X (iregs[10]),
193 X (iregs[11]),
194 X (iregs[12]),
195 X (iregs[13]),
196 X (iregs[14]),
197 X (iregs[15]),
198 X (iregs[16]),
199 X (iregs[17]),
200 X (iregs[18]),
201 X (iregs[19]),
202 X (iregs[20]),
203 X (iregs[21]),
204 X (iregs[22]),
205 X (iregs[23]),
206 X (iregs[24]),
207 X (iregs[25]),
208 X (iregs[26]),
209 X (iregs[27]),
210 X (iregs[28]),
211 X (iregs[29]),
212 X (iregs[30]),
213 X (iregs[31]),
214
215 X (fregs[0]), /* f0 */
216 X (fregs[1]),
217 X (fregs[2]),
218 X (fregs[3]),
219 X (fregs[4]),
220 X (fregs[5]),
221 X (fregs[6]),
222 X (fregs[7]),
223 X (fregs[8]),
224 X (fregs[9]),
225 X (fregs[10]),
226 X (fregs[11]),
227 X (fregs[12]),
228 X (fregs[13]),
229 X (fregs[14]),
230 X (fregs[15]),
231 X (fregs[16]),
232 X (fregs[17]),
233 X (fregs[18]),
234 X (fregs[19]),
235 X (fregs[20]),
236 X (fregs[21]),
237 X (fregs[22]),
238 X (fregs[23]),
239 X (fregs[24]),
240 X (fregs[25]),
241 X (fregs[26]),
242 X (fregs[27]),
243 X (fregs[28]),
244 X (fregs[29]),
245 X (fregs[30]),
246 X (fregs[31]),
247
248 X (srr0), /* IAR (PC) */
249 X (srr1), /* MSR (PS) */
250 X (cr), /* CR */
251 X (lr), /* LR */
252 X (ctr), /* CTR */
253 X (xer), /* XER */
254 X (mq) /* MQ */
c906108c
SS
255};
256
257#endif /* rs6000 */
258
c906108c
SS
259#if defined (I386) || defined (M68K) || defined (rs6000)
260
261/* Return the offset relative to the start of the per-thread data to the
262 saved context block. */
263
264static unsigned long
fba45db2 265registers_addr (int pid)
c906108c
SS
266{
267 CORE_ADDR stblock;
c5aa993b 268 int ecpoff = offsetof (st_t, ecp);
c906108c
SS
269 CORE_ADDR ecp;
270
271 errno = 0;
c5aa993b 272 stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE) 0,
c906108c
SS
273 0);
274 if (errno)
275 perror_with_name ("ptrace(PTRACE_THREADUSER)");
276
c5aa993b 277 ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) ecpoff,
c906108c
SS
278 0);
279 if (errno)
280 perror_with_name ("ptrace(PTRACE_PEEKTHREAD)");
281
282 return ecp - stblock;
283}
284
285/* Fetch one or more registers from the inferior. REGNO == -1 to get
286 them all. We actually fetch more than requested, when convenient,
287 marking them as valid so we won't fetch them again. */
288
289void
fba45db2 290fetch_inferior_registers (int regno)
c906108c
SS
291{
292 int reglo, reghi;
293 int i;
294 unsigned long ecp;
295
296 if (regno == -1)
297 {
298 reglo = 0;
299 reghi = NUM_REGS - 1;
300 }
301 else
302 reglo = reghi = regno;
303
39f77062 304 ecp = registers_addr (PIDGET (inferior_ptid));
c906108c 305
6789195b 306 {
123a958e 307 char buf[MAX_REGISTER_SIZE];
6789195b
AC
308 for (regno = reglo; regno <= reghi; regno++)
309 {
310 int ptrace_fun = PTRACE_PEEKTHREAD;
311
c906108c 312#ifdef M68K
6789195b 313 ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
c906108c 314#endif
6789195b 315
3acba339 316 for (i = 0; i < register_size (current_gdbarch, regno); i += sizeof (int))
6789195b
AC
317 {
318 unsigned int reg;
319
320 errno = 0;
321 reg = ptrace (ptrace_fun, PIDGET (inferior_ptid),
322 (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), 0);
323 if (errno)
324 perror_with_name ("ptrace(PTRACE_PEEKUSP)");
325
326 *(int *) &buf[i] = reg;
327 }
23a6d369 328 regcache_raw_supply (current_regcache, regno, buf);
6789195b
AC
329 }
330 }
c906108c
SS
331}
332
333/* Store our register values back into the inferior.
334 If REGNO is -1, do this for all registers.
335 Otherwise, REGNO specifies which register (so we can save time). */
336
c906108c 337void
fba45db2 338store_inferior_registers (int regno)
c906108c
SS
339{
340 int reglo, reghi;
341 int i;
342 unsigned long ecp;
343
344 if (regno == -1)
345 {
346 reglo = 0;
347 reghi = NUM_REGS - 1;
348 }
349 else
350 reglo = reghi = regno;
351
39f77062 352 ecp = registers_addr (PIDGET (inferior_ptid));
c906108c
SS
353
354 for (regno = reglo; regno <= reghi; regno++)
355 {
356 int ptrace_fun = PTRACE_POKEUSER;
357
358 if (CANNOT_STORE_REGISTER (regno))
359 continue;
360
361#ifdef M68K
362 ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
363#endif
364
3acba339 365 for (i = 0; i < register_size (current_gdbarch, regno); i += sizeof (int))
c906108c
SS
366 {
367 unsigned int reg;
368
62700349 369 reg = *(unsigned int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno) + i];
c906108c
SS
370
371 errno = 0;
39f77062 372 ptrace (ptrace_fun, PIDGET (inferior_ptid),
c906108c
SS
373 (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), reg);
374 if (errno)
375 perror_with_name ("ptrace(PTRACE_POKEUSP)");
376 }
377 }
378}
379#endif /* defined (I386) || defined (M68K) || defined (rs6000) */
380
381/* Wait for child to do something. Return pid of child, or -1 in case
382 of error; store status through argument pointer OURSTATUS. */
383
39f77062
KB
384ptid_t
385child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c
SS
386{
387 int save_errno;
388 int thread;
389 union wait status;
39f77062 390 int pid;
c906108c
SS
391
392 while (1)
393 {
394 int sig;
395
c5aa993b 396 set_sigint_trap (); /* Causes SIGINT to be passed on to the
c906108c
SS
397 attached process. */
398 pid = wait (&status);
399
400 save_errno = errno;
401
c5aa993b 402 clear_sigint_trap ();
c906108c
SS
403
404 if (pid == -1)
405 {
406 if (save_errno == EINTR)
407 continue;
408 fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
c5aa993b 409 safe_strerror (save_errno));
c906108c
SS
410 /* Claim it exited with unknown signal. */
411 ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
412 ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
413 return -1;
414 }
415
39f77062 416 if (pid != PIDGET (inferior_ptid)) /* Some other process?!? */
c906108c
SS
417 continue;
418
419 thread = status.w_tid; /* Get thread id from status */
420
421 /* Initial thread value can only be acquired via wait, so we have to
c5aa993b 422 resort to this hack. */
c906108c 423
39f77062 424 if (TIDGET (inferior_ptid) == 0 && thread != 0)
c906108c 425 {
39f77062
KB
426 inferior_ptid = MERGEPID (PIDGET (inferior_ptid), thread);
427 add_thread (inferior_ptid);
c906108c
SS
428 }
429
39f77062 430 ptid = BUILDPID (pid, thread);
c906108c
SS
431
432 /* We've become a single threaded process again. */
433 if (thread == 0)
39f77062 434 inferior_ptid = ptid;
c906108c
SS
435
436 /* Check for thread creation. */
c5aa993b
JM
437 if (WIFSTOPPED (status)
438 && WSTOPSIG (status) == SIGTRAP
39f77062 439 && !in_thread_list (ptid))
c906108c
SS
440 {
441 int realsig;
442
39f77062
KB
443 realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid),
444 (PTRACE_ARG3_TYPE) 0, 0);
c906108c
SS
445
446 if (realsig == SIGNEWTHREAD)
447 {
448 /* It's a new thread notification. We don't want to much with
c5aa993b 449 realsig -- the code in wait_for_inferior expects SIGTRAP. */
c906108c
SS
450 ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
451 ourstatus->value.sig = TARGET_SIGNAL_0;
39f77062 452 return ptid;
c906108c
SS
453 }
454 else
455 error ("Signal for unknown thread was not SIGNEWTHREAD");
456 }
457
458 /* Check for thread termination. */
c5aa993b
JM
459 else if (WIFSTOPPED (status)
460 && WSTOPSIG (status) == SIGTRAP
39f77062 461 && in_thread_list (ptid))
c906108c
SS
462 {
463 int realsig;
464
39f77062
KB
465 realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid),
466 (PTRACE_ARG3_TYPE) 0, 0);
c906108c
SS
467
468 if (realsig == SIGTHREADEXIT)
469 {
39f77062 470 ptrace (PTRACE_CONT, PIDGET (ptid), (PTRACE_ARG3_TYPE) 0, 0);
c906108c
SS
471 continue;
472 }
473 }
474
475#ifdef SPARC
476 /* SPARC Lynx uses an byte reversed wait status; we must use the
c5aa993b
JM
477 host macros to access it. These lines just a copy of
478 store_waitstatus. We can't use CHILD_SPECIAL_WAITSTATUS
479 because target.c can't include the Lynx <sys/wait.h>. */
c906108c
SS
480 if (WIFEXITED (status))
481 {
482 ourstatus->kind = TARGET_WAITKIND_EXITED;
483 ourstatus->value.integer = WEXITSTATUS (status);
484 }
485 else if (!WIFSTOPPED (status))
486 {
487 ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
488 ourstatus->value.sig =
489 target_signal_from_host (WTERMSIG (status));
490 }
491 else
492 {
493 ourstatus->kind = TARGET_WAITKIND_STOPPED;
494 ourstatus->value.sig =
495 target_signal_from_host (WSTOPSIG (status));
496 }
497#else
498 store_waitstatus (ourstatus, status.w_status);
499#endif
500
39f77062 501 return ptid;
c906108c
SS
502 }
503}
504
505/* Return nonzero if the given thread is still alive. */
506int
39f77062 507child_thread_alive (ptid_t ptid)
c906108c 508{
39f77062
KB
509 int pid = PIDGET (ptid);
510
c906108c
SS
511 /* Arggh. Apparently pthread_kill only works for threads within
512 the process that calls pthread_kill.
513
514 We want to avoid the lynx signal extensions as they simply don't
515 map well to the generic gdb interface we want to keep.
516
517 All we want to do is determine if a particular thread is alive;
518 it appears as if we can just make a harmless thread specific
519 ptrace call to do that. */
520 return (ptrace (PTRACE_THREADUSER, pid, 0, 0) != -1);
521}
522
523/* Resume execution of the inferior process.
524 If STEP is nonzero, single-step it.
525 If SIGNAL is nonzero, give it that signal. */
526
527void
39f77062 528child_resume (ptid_t ptid, int step, enum target_signal signal)
c906108c
SS
529{
530 int func;
39f77062 531 int pid = PIDGET (ptid);
c906108c
SS
532
533 errno = 0;
534
535 /* If pid == -1, then we want to step/continue all threads, else
536 we only want to step/continue a single thread. */
537 if (pid == -1)
538 {
39f77062 539 pid = PIDGET (inferior_ptid);
c906108c
SS
540 func = step ? PTRACE_SINGLESTEP : PTRACE_CONT;
541 }
542 else
543 func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT_ONE;
544
545
546 /* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
547 it was. (If GDB wanted it to start some other way, we have already
548 written a new PC value to the child.)
549
550 If this system does not support PT_STEP, a higher level function will
551 have called single_step() to transmute the step request into a
552 continue request (by setting breakpoints on all possible successor
553 instructions), so we don't have to worry about that here. */
554
555 ptrace (func, pid, (PTRACE_ARG3_TYPE) 1, target_signal_to_host (signal));
556
557 if (errno)
558 perror_with_name ("ptrace");
559}
560
561/* Convert a Lynx process ID to a string. Returns the string in a static
562 buffer. */
563
564char *
39f77062 565child_pid_to_str (ptid_t ptid)
c906108c
SS
566{
567 static char buf[40];
568
39f77062 569 sprintf (buf, "process %d thread %d", PIDGET (ptid), TIDGET (ptid));
c906108c
SS
570
571 return buf;
572}
573
574/* Extract the register values out of the core file and store
575 them where `read_register' will find them.
576
577 CORE_REG_SECT points to the register values themselves, read into memory.
578 CORE_REG_SIZE is the size of that area.
579 WHICH says which set of registers we are handling (0 = int, 2 = float
c5aa993b 580 on machines where they are discontiguous).
c906108c 581 REG_ADDR is the offset from u.u_ar0 to the register values relative to
c5aa993b
JM
582 core_reg_sect. This is used with old-fashioned core files to
583 locate the registers in a large upage-plus-stack ".reg" section.
584 Original upage address X is at location core_reg_sect+x+reg_addr.
c906108c
SS
585 */
586
587static void
fba45db2
KB
588fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
589 CORE_ADDR reg_addr)
c906108c
SS
590{
591 struct st_entry s;
592 unsigned int regno;
593
594 for (regno = 0; regno < NUM_REGS; regno++)
595 if (regmap[regno] != -1)
23a6d369
AC
596 regcache_raw_supply (current_regcache, regno,
597 core_reg_sect + offsetof (st_t, ec) + regmap[regno]);
c906108c
SS
598
599#ifdef SPARC
600/* Fetching this register causes all of the I & L regs to be read from the
601 stack and validated. */
602
603 fetch_inferior_registers (I0_REGNUM);
604#endif
605}
c906108c 606\f
c5aa993b 607
c906108c
SS
608/* Register that we are able to handle lynx core file formats.
609 FIXME: is this really bfd_target_unknown_flavour? */
610
611static struct core_fns lynx_core_fns =
612{
2acceee2
JM
613 bfd_target_unknown_flavour, /* core_flavour */
614 default_check_format, /* check_format */
615 default_core_sniffer, /* core_sniffer */
616 fetch_core_registers, /* core_read_registers */
617 NULL /* next */
c906108c
SS
618};
619
620void
fba45db2 621_initialize_core_lynx (void)
c906108c 622{
00e32a35 623 deprecated_add_core_fns (&lynx_core_fns);
c906108c 624}
This page took 0.590505 seconds and 4 git commands to generate.