1130812Smarcel/* Native-dependent code for LynxOS.
2130812Smarcel
3130812Smarcel   Copyright 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2003 Free
4130812Smarcel   Software Foundation, Inc.
5130812Smarcel
6130812Smarcel   This file is part of GDB.
7130812Smarcel
8130812Smarcel   This program is free software; you can redistribute it and/or modify
9130812Smarcel   it under the terms of the GNU General Public License as published by
10130812Smarcel   the Free Software Foundation; either version 2 of the License, or
11130812Smarcel   (at your option) any later version.
12130812Smarcel
13130812Smarcel   This program is distributed in the hope that it will be useful,
14130812Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
15130812Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16130812Smarcel   GNU General Public License for more details.
17130812Smarcel
18130812Smarcel   You should have received a copy of the GNU General Public License
19130812Smarcel   along with this program; if not, write to the Free Software
20130812Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
21130812Smarcel   Boston, MA 02111-1307, USA.  */
22130812Smarcel
23130812Smarcel#include "defs.h"
24130812Smarcel#include "frame.h"
25130812Smarcel#include "inferior.h"
26130812Smarcel#include "target.h"
27130812Smarcel#include "gdbcore.h"
28130812Smarcel#include "regcache.h"
29130812Smarcel
30130812Smarcel#include <sys/ptrace.h>
31130812Smarcel#Include "gdb_wait.h"
32130812Smarcel#include <sys/fpp.h>
33130812Smarcel
34130812Smarcelstatic unsigned long registers_addr (int pid);
35130812Smarcelstatic void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
36130812Smarcel
37130812Smarcel#define X(ENTRY)(offsetof(struct econtext, ENTRY))
38130812Smarcel
39130812Smarcel#ifdef I386
40130812Smarcel/* Mappings from tm-i386v.h */
41130812Smarcel
42130812Smarcelstatic int regmap[] =
43130812Smarcel{
44130812Smarcel  X (eax),
45130812Smarcel  X (ecx),
46130812Smarcel  X (edx),
47130812Smarcel  X (ebx),
48130812Smarcel  X (esp),			/* sp */
49130812Smarcel  X (ebp),			/* fp */
50130812Smarcel  X (esi),
51130812Smarcel  X (edi),
52130812Smarcel  X (eip),			/* pc */
53130812Smarcel  X (flags),			/* ps */
54130812Smarcel  X (cs),
55130812Smarcel  X (ss),
56130812Smarcel  X (ds),
57130812Smarcel  X (es),
58130812Smarcel  X (ecode),			/* Lynx doesn't give us either fs or gs, so */
59130812Smarcel  X (fault),			/* we just substitute these two in the hopes
60130812Smarcel				   that they are useful. */
61130812Smarcel};
62130812Smarcel#endif /* I386 */
63130812Smarcel
64130812Smarcel#ifdef M68K
65130812Smarcel/* Mappings from tm-m68k.h */
66130812Smarcel
67130812Smarcelstatic int regmap[] =
68130812Smarcel{
69130812Smarcel  X (regs[0]),			/* d0 */
70130812Smarcel  X (regs[1]),			/* d1 */
71130812Smarcel  X (regs[2]),			/* d2 */
72130812Smarcel  X (regs[3]),			/* d3 */
73130812Smarcel  X (regs[4]),			/* d4 */
74130812Smarcel  X (regs[5]),			/* d5 */
75130812Smarcel  X (regs[6]),			/* d6 */
76130812Smarcel  X (regs[7]),			/* d7 */
77130812Smarcel  X (regs[8]),			/* a0 */
78130812Smarcel  X (regs[9]),			/* a1 */
79130812Smarcel  X (regs[10]),			/* a2 */
80130812Smarcel  X (regs[11]),			/* a3 */
81130812Smarcel  X (regs[12]),			/* a4 */
82130812Smarcel  X (regs[13]),			/* a5 */
83130812Smarcel  X (regs[14]),			/* fp */
84130812Smarcel  offsetof (st_t, usp) - offsetof (st_t, ec),	/* sp */
85130812Smarcel  X (status),			/* ps */
86130812Smarcel  X (pc),
87130812Smarcel
88130812Smarcel  X (fregs[0 * 3]),		/* fp0 */
89130812Smarcel  X (fregs[1 * 3]),		/* fp1 */
90130812Smarcel  X (fregs[2 * 3]),		/* fp2 */
91130812Smarcel  X (fregs[3 * 3]),		/* fp3 */
92130812Smarcel  X (fregs[4 * 3]),		/* fp4 */
93130812Smarcel  X (fregs[5 * 3]),		/* fp5 */
94130812Smarcel  X (fregs[6 * 3]),		/* fp6 */
95130812Smarcel  X (fregs[7 * 3]),		/* fp7 */
96130812Smarcel
97130812Smarcel  X (fcregs[0]),		/* fpcontrol */
98130812Smarcel  X (fcregs[1]),		/* fpstatus */
99130812Smarcel  X (fcregs[2]),		/* fpiaddr */
100130812Smarcel  X (ssw),			/* fpcode */
101130812Smarcel  X (fault),			/* fpflags */
102130812Smarcel};
103130812Smarcel#endif /* M68K */
104130812Smarcel
105130812Smarcel#ifdef SPARC
106130812Smarcel/* Mappings from tm-sparc.h */
107130812Smarcel
108130812Smarcel#define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
109130812Smarcel
110130812Smarcelstatic int regmap[] =
111130812Smarcel{
112130812Smarcel  -1,				/* g0 */
113130812Smarcel  X (g1),
114130812Smarcel  X (g2),
115130812Smarcel  X (g3),
116130812Smarcel  X (g4),
117130812Smarcel  -1,				/* g5->g7 aren't saved by Lynx */
118130812Smarcel  -1,
119130812Smarcel  -1,
120130812Smarcel
121130812Smarcel  X (o[0]),
122130812Smarcel  X (o[1]),
123130812Smarcel  X (o[2]),
124130812Smarcel  X (o[3]),
125130812Smarcel  X (o[4]),
126130812Smarcel  X (o[5]),
127130812Smarcel  X (o[6]),			/* sp */
128130812Smarcel  X (o[7]),			/* ra */
129130812Smarcel
130130812Smarcel  -1, -1, -1, -1, -1, -1, -1, -1,	/* l0 -> l7 */
131130812Smarcel
132130812Smarcel  -1, -1, -1, -1, -1, -1, -1, -1,	/* i0 -> i7 */
133130812Smarcel
134130812Smarcel  FX (f.fregs[0]),		/* f0 */
135130812Smarcel  FX (f.fregs[1]),
136130812Smarcel  FX (f.fregs[2]),
137130812Smarcel  FX (f.fregs[3]),
138130812Smarcel  FX (f.fregs[4]),
139130812Smarcel  FX (f.fregs[5]),
140130812Smarcel  FX (f.fregs[6]),
141130812Smarcel  FX (f.fregs[7]),
142130812Smarcel  FX (f.fregs[8]),
143130812Smarcel  FX (f.fregs[9]),
144130812Smarcel  FX (f.fregs[10]),
145130812Smarcel  FX (f.fregs[11]),
146130812Smarcel  FX (f.fregs[12]),
147130812Smarcel  FX (f.fregs[13]),
148130812Smarcel  FX (f.fregs[14]),
149130812Smarcel  FX (f.fregs[15]),
150130812Smarcel  FX (f.fregs[16]),
151130812Smarcel  FX (f.fregs[17]),
152130812Smarcel  FX (f.fregs[18]),
153130812Smarcel  FX (f.fregs[19]),
154130812Smarcel  FX (f.fregs[20]),
155130812Smarcel  FX (f.fregs[21]),
156130812Smarcel  FX (f.fregs[22]),
157130812Smarcel  FX (f.fregs[23]),
158130812Smarcel  FX (f.fregs[24]),
159130812Smarcel  FX (f.fregs[25]),
160130812Smarcel  FX (f.fregs[26]),
161130812Smarcel  FX (f.fregs[27]),
162130812Smarcel  FX (f.fregs[28]),
163130812Smarcel  FX (f.fregs[29]),
164130812Smarcel  FX (f.fregs[30]),
165130812Smarcel  FX (f.fregs[31]),
166130812Smarcel
167130812Smarcel  X (y),
168130812Smarcel  X (psr),
169130812Smarcel  X (wim),
170130812Smarcel  X (tbr),
171130812Smarcel  X (pc),
172130812Smarcel  X (npc),
173130812Smarcel  FX (fsr),			/* fpsr */
174130812Smarcel  -1,				/* cpsr */
175130812Smarcel};
176130812Smarcel#endif /* SPARC */
177130812Smarcel
178130812Smarcel#ifdef rs6000
179130812Smarcel
180130812Smarcelstatic int regmap[] =
181130812Smarcel{
182130812Smarcel  X (iregs[0]),			/* r0 */
183130812Smarcel  X (iregs[1]),
184130812Smarcel  X (iregs[2]),
185130812Smarcel  X (iregs[3]),
186130812Smarcel  X (iregs[4]),
187130812Smarcel  X (iregs[5]),
188130812Smarcel  X (iregs[6]),
189130812Smarcel  X (iregs[7]),
190130812Smarcel  X (iregs[8]),
191130812Smarcel  X (iregs[9]),
192130812Smarcel  X (iregs[10]),
193130812Smarcel  X (iregs[11]),
194130812Smarcel  X (iregs[12]),
195130812Smarcel  X (iregs[13]),
196130812Smarcel  X (iregs[14]),
197130812Smarcel  X (iregs[15]),
198130812Smarcel  X (iregs[16]),
199130812Smarcel  X (iregs[17]),
200130812Smarcel  X (iregs[18]),
201130812Smarcel  X (iregs[19]),
202130812Smarcel  X (iregs[20]),
203130812Smarcel  X (iregs[21]),
204130812Smarcel  X (iregs[22]),
205130812Smarcel  X (iregs[23]),
206130812Smarcel  X (iregs[24]),
207130812Smarcel  X (iregs[25]),
208130812Smarcel  X (iregs[26]),
209130812Smarcel  X (iregs[27]),
210130812Smarcel  X (iregs[28]),
211130812Smarcel  X (iregs[29]),
212130812Smarcel  X (iregs[30]),
213130812Smarcel  X (iregs[31]),
214130812Smarcel
215130812Smarcel  X (fregs[0]),			/* f0 */
216130812Smarcel  X (fregs[1]),
217130812Smarcel  X (fregs[2]),
218130812Smarcel  X (fregs[3]),
219130812Smarcel  X (fregs[4]),
220130812Smarcel  X (fregs[5]),
221130812Smarcel  X (fregs[6]),
222130812Smarcel  X (fregs[7]),
223130812Smarcel  X (fregs[8]),
224130812Smarcel  X (fregs[9]),
225130812Smarcel  X (fregs[10]),
226130812Smarcel  X (fregs[11]),
227130812Smarcel  X (fregs[12]),
228130812Smarcel  X (fregs[13]),
229130812Smarcel  X (fregs[14]),
230130812Smarcel  X (fregs[15]),
231130812Smarcel  X (fregs[16]),
232130812Smarcel  X (fregs[17]),
233130812Smarcel  X (fregs[18]),
234130812Smarcel  X (fregs[19]),
235130812Smarcel  X (fregs[20]),
236130812Smarcel  X (fregs[21]),
237130812Smarcel  X (fregs[22]),
238130812Smarcel  X (fregs[23]),
239130812Smarcel  X (fregs[24]),
240130812Smarcel  X (fregs[25]),
241130812Smarcel  X (fregs[26]),
242130812Smarcel  X (fregs[27]),
243130812Smarcel  X (fregs[28]),
244130812Smarcel  X (fregs[29]),
245130812Smarcel  X (fregs[30]),
246130812Smarcel  X (fregs[31]),
247130812Smarcel
248130812Smarcel  X (srr0),			/* IAR (PC) */
249130812Smarcel  X (srr1),			/* MSR (PS) */
250130812Smarcel  X (cr),			/* CR */
251130812Smarcel  X (lr),			/* LR */
252130812Smarcel  X (ctr),			/* CTR */
253130812Smarcel  X (xer),			/* XER */
254130812Smarcel  X (mq)			/* MQ */
255130812Smarcel};
256130812Smarcel
257130812Smarcel#endif /* rs6000 */
258130812Smarcel
259130812Smarcel#if defined (I386) || defined (M68K) || defined (rs6000)
260130812Smarcel
261130812Smarcel/* Return the offset relative to the start of the per-thread data to the
262130812Smarcel   saved context block.  */
263130812Smarcel
264130812Smarcelstatic unsigned long
265130812Smarcelregisters_addr (int pid)
266130812Smarcel{
267130812Smarcel  CORE_ADDR stblock;
268130812Smarcel  int ecpoff = offsetof (st_t, ecp);
269130812Smarcel  CORE_ADDR ecp;
270130812Smarcel
271130812Smarcel  errno = 0;
272130812Smarcel  stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE) 0,
273130812Smarcel				0);
274130812Smarcel  if (errno)
275130812Smarcel    perror_with_name ("ptrace(PTRACE_THREADUSER)");
276130812Smarcel
277130812Smarcel  ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) ecpoff,
278130812Smarcel			    0);
279130812Smarcel  if (errno)
280130812Smarcel    perror_with_name ("ptrace(PTRACE_PEEKTHREAD)");
281130812Smarcel
282130812Smarcel  return ecp - stblock;
283130812Smarcel}
284130812Smarcel
285130812Smarcel/* Fetch one or more registers from the inferior.  REGNO == -1 to get
286130812Smarcel   them all.  We actually fetch more than requested, when convenient,
287130812Smarcel   marking them as valid so we won't fetch them again.  */
288130812Smarcel
289130812Smarcelvoid
290130812Smarcelfetch_inferior_registers (int regno)
291130812Smarcel{
292130812Smarcel  int reglo, reghi;
293130812Smarcel  int i;
294130812Smarcel  unsigned long ecp;
295130812Smarcel
296130812Smarcel  if (regno == -1)
297130812Smarcel    {
298130812Smarcel      reglo = 0;
299130812Smarcel      reghi = NUM_REGS - 1;
300130812Smarcel    }
301130812Smarcel  else
302130812Smarcel    reglo = reghi = regno;
303130812Smarcel
304130812Smarcel  ecp = registers_addr (PIDGET (inferior_ptid));
305130812Smarcel
306130812Smarcel  {
307130812Smarcel    char buf[MAX_REGISTER_SIZE];
308130812Smarcel    for (regno = reglo; regno <= reghi; regno++)
309130812Smarcel      {
310130812Smarcel	int ptrace_fun = PTRACE_PEEKTHREAD;
311130812Smarcel
312130812Smarcel#ifdef M68K
313130812Smarcel	ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
314130812Smarcel#endif
315130812Smarcel
316130812Smarcel	for (i = 0; i < DEPRECATED_REGISTER_RAW_SIZE (regno); i += sizeof (int))
317130812Smarcel	  {
318130812Smarcel	    unsigned int reg;
319130812Smarcel
320130812Smarcel	    errno = 0;
321130812Smarcel	    reg = ptrace (ptrace_fun, PIDGET (inferior_ptid),
322130812Smarcel			  (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), 0);
323130812Smarcel	    if (errno)
324130812Smarcel	      perror_with_name ("ptrace(PTRACE_PEEKUSP)");
325130812Smarcel
326130812Smarcel	    *(int *) &buf[i] = reg;
327130812Smarcel	  }
328130812Smarcel	supply_register (regno, buf);
329130812Smarcel      }
330130812Smarcel  }
331130812Smarcel}
332130812Smarcel
333130812Smarcel/* Store our register values back into the inferior.
334130812Smarcel   If REGNO is -1, do this for all registers.
335130812Smarcel   Otherwise, REGNO specifies which register (so we can save time).  */
336130812Smarcel
337130812Smarcelvoid
338130812Smarcelstore_inferior_registers (int regno)
339130812Smarcel{
340130812Smarcel  int reglo, reghi;
341130812Smarcel  int i;
342130812Smarcel  unsigned long ecp;
343130812Smarcel
344130812Smarcel  if (regno == -1)
345130812Smarcel    {
346130812Smarcel      reglo = 0;
347130812Smarcel      reghi = NUM_REGS - 1;
348130812Smarcel    }
349130812Smarcel  else
350130812Smarcel    reglo = reghi = regno;
351130812Smarcel
352130812Smarcel  ecp = registers_addr (PIDGET (inferior_ptid));
353130812Smarcel
354130812Smarcel  for (regno = reglo; regno <= reghi; regno++)
355130812Smarcel    {
356130812Smarcel      int ptrace_fun = PTRACE_POKEUSER;
357130812Smarcel
358130812Smarcel      if (CANNOT_STORE_REGISTER (regno))
359130812Smarcel	continue;
360130812Smarcel
361130812Smarcel#ifdef M68K
362130812Smarcel      ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
363130812Smarcel#endif
364130812Smarcel
365130812Smarcel      for (i = 0; i < DEPRECATED_REGISTER_RAW_SIZE (regno); i += sizeof (int))
366130812Smarcel	{
367130812Smarcel	  unsigned int reg;
368130812Smarcel
369130812Smarcel	  reg = *(unsigned int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno) + i];
370130812Smarcel
371130812Smarcel	  errno = 0;
372130812Smarcel	  ptrace (ptrace_fun, PIDGET (inferior_ptid),
373130812Smarcel		  (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), reg);
374130812Smarcel	  if (errno)
375130812Smarcel	    perror_with_name ("ptrace(PTRACE_POKEUSP)");
376130812Smarcel	}
377130812Smarcel    }
378130812Smarcel}
379130812Smarcel#endif /* defined (I386) || defined (M68K) || defined (rs6000) */
380130812Smarcel
381130812Smarcel/* Wait for child to do something.  Return pid of child, or -1 in case
382130812Smarcel   of error; store status through argument pointer OURSTATUS.  */
383130812Smarcel
384130812Smarcelptid_t
385130812Smarcelchild_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
386130812Smarcel{
387130812Smarcel  int save_errno;
388130812Smarcel  int thread;
389130812Smarcel  union wait status;
390130812Smarcel  int pid;
391130812Smarcel
392130812Smarcel  while (1)
393130812Smarcel    {
394130812Smarcel      int sig;
395130812Smarcel
396130812Smarcel      set_sigint_trap ();	/* Causes SIGINT to be passed on to the
397130812Smarcel				   attached process. */
398130812Smarcel      pid = wait (&status);
399130812Smarcel
400130812Smarcel      save_errno = errno;
401130812Smarcel
402130812Smarcel      clear_sigint_trap ();
403130812Smarcel
404130812Smarcel      if (pid == -1)
405130812Smarcel	{
406130812Smarcel	  if (save_errno == EINTR)
407130812Smarcel	    continue;
408130812Smarcel	  fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
409130812Smarcel			      safe_strerror (save_errno));
410130812Smarcel	  /* Claim it exited with unknown signal.  */
411130812Smarcel	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
412130812Smarcel	  ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
413130812Smarcel	  return -1;
414130812Smarcel	}
415130812Smarcel
416130812Smarcel      if (pid != PIDGET (inferior_ptid))	/* Some other process?!? */
417130812Smarcel	continue;
418130812Smarcel
419130812Smarcel      thread = status.w_tid;	/* Get thread id from status */
420130812Smarcel
421130812Smarcel      /* Initial thread value can only be acquired via wait, so we have to
422130812Smarcel         resort to this hack.  */
423130812Smarcel
424130812Smarcel      if (TIDGET (inferior_ptid) == 0 && thread != 0)
425130812Smarcel	{
426130812Smarcel	  inferior_ptid = MERGEPID (PIDGET (inferior_ptid), thread);
427130812Smarcel	  add_thread (inferior_ptid);
428130812Smarcel	}
429130812Smarcel
430130812Smarcel      ptid = BUILDPID (pid, thread);
431130812Smarcel
432130812Smarcel      /* We've become a single threaded process again.  */
433130812Smarcel      if (thread == 0)
434130812Smarcel	inferior_ptid = ptid;
435130812Smarcel
436130812Smarcel      /* Check for thread creation.  */
437130812Smarcel      if (WIFSTOPPED (status)
438130812Smarcel	  && WSTOPSIG (status) == SIGTRAP
439130812Smarcel	  && !in_thread_list (ptid))
440130812Smarcel	{
441130812Smarcel	  int realsig;
442130812Smarcel
443130812Smarcel	  realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid),
444130812Smarcel	                    (PTRACE_ARG3_TYPE) 0, 0);
445130812Smarcel
446130812Smarcel	  if (realsig == SIGNEWTHREAD)
447130812Smarcel	    {
448130812Smarcel	      /* It's a new thread notification.  We don't want to much with
449130812Smarcel	         realsig -- the code in wait_for_inferior expects SIGTRAP. */
450130812Smarcel	      ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
451130812Smarcel	      ourstatus->value.sig = TARGET_SIGNAL_0;
452130812Smarcel	      return ptid;
453130812Smarcel	    }
454130812Smarcel	  else
455130812Smarcel	    error ("Signal for unknown thread was not SIGNEWTHREAD");
456130812Smarcel	}
457130812Smarcel
458130812Smarcel      /* Check for thread termination.  */
459130812Smarcel      else if (WIFSTOPPED (status)
460130812Smarcel	       && WSTOPSIG (status) == SIGTRAP
461130812Smarcel	       && in_thread_list (ptid))
462130812Smarcel	{
463130812Smarcel	  int realsig;
464130812Smarcel
465130812Smarcel	  realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid),
466130812Smarcel	                    (PTRACE_ARG3_TYPE) 0, 0);
467130812Smarcel
468130812Smarcel	  if (realsig == SIGTHREADEXIT)
469130812Smarcel	    {
470130812Smarcel	      ptrace (PTRACE_CONT, PIDGET (ptid), (PTRACE_ARG3_TYPE) 0, 0);
471130812Smarcel	      continue;
472130812Smarcel	    }
473130812Smarcel	}
474130812Smarcel
475130812Smarcel#ifdef SPARC
476130812Smarcel      /* SPARC Lynx uses an byte reversed wait status; we must use the
477130812Smarcel         host macros to access it.  These lines just a copy of
478130812Smarcel         store_waitstatus.  We can't use CHILD_SPECIAL_WAITSTATUS
479130812Smarcel         because target.c can't include the Lynx <sys/wait.h>.  */
480130812Smarcel      if (WIFEXITED (status))
481130812Smarcel	{
482130812Smarcel	  ourstatus->kind = TARGET_WAITKIND_EXITED;
483130812Smarcel	  ourstatus->value.integer = WEXITSTATUS (status);
484130812Smarcel	}
485130812Smarcel      else if (!WIFSTOPPED (status))
486130812Smarcel	{
487130812Smarcel	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
488130812Smarcel	  ourstatus->value.sig =
489130812Smarcel	    target_signal_from_host (WTERMSIG (status));
490130812Smarcel	}
491130812Smarcel      else
492130812Smarcel	{
493130812Smarcel	  ourstatus->kind = TARGET_WAITKIND_STOPPED;
494130812Smarcel	  ourstatus->value.sig =
495130812Smarcel	    target_signal_from_host (WSTOPSIG (status));
496130812Smarcel	}
497130812Smarcel#else
498130812Smarcel      store_waitstatus (ourstatus, status.w_status);
499130812Smarcel#endif
500130812Smarcel
501130812Smarcel      return ptid;
502130812Smarcel    }
503130812Smarcel}
504130812Smarcel
505130812Smarcel/* Return nonzero if the given thread is still alive.  */
506130812Smarcelint
507130812Smarcelchild_thread_alive (ptid_t ptid)
508130812Smarcel{
509130812Smarcel  int pid = PIDGET (ptid);
510130812Smarcel
511130812Smarcel  /* Arggh.  Apparently pthread_kill only works for threads within
512130812Smarcel     the process that calls pthread_kill.
513130812Smarcel
514130812Smarcel     We want to avoid the lynx signal extensions as they simply don't
515130812Smarcel     map well to the generic gdb interface we want to keep.
516130812Smarcel
517130812Smarcel     All we want to do is determine if a particular thread is alive;
518130812Smarcel     it appears as if we can just make a harmless thread specific
519130812Smarcel     ptrace call to do that.  */
520130812Smarcel  return (ptrace (PTRACE_THREADUSER, pid, 0, 0) != -1);
521130812Smarcel}
522130812Smarcel
523130812Smarcel/* Resume execution of the inferior process.
524130812Smarcel   If STEP is nonzero, single-step it.
525130812Smarcel   If SIGNAL is nonzero, give it that signal.  */
526130812Smarcel
527130812Smarcelvoid
528130812Smarcelchild_resume (ptid_t ptid, int step, enum target_signal signal)
529130812Smarcel{
530130812Smarcel  int func;
531130812Smarcel  int pid = PIDGET (ptid);
532130812Smarcel
533130812Smarcel  errno = 0;
534130812Smarcel
535130812Smarcel  /* If pid == -1, then we want to step/continue all threads, else
536130812Smarcel     we only want to step/continue a single thread.  */
537130812Smarcel  if (pid == -1)
538130812Smarcel    {
539130812Smarcel      pid = PIDGET (inferior_ptid);
540130812Smarcel      func = step ? PTRACE_SINGLESTEP : PTRACE_CONT;
541130812Smarcel    }
542130812Smarcel  else
543130812Smarcel    func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT_ONE;
544130812Smarcel
545130812Smarcel
546130812Smarcel  /* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
547130812Smarcel     it was.  (If GDB wanted it to start some other way, we have already
548130812Smarcel     written a new PC value to the child.)
549130812Smarcel
550130812Smarcel     If this system does not support PT_STEP, a higher level function will
551130812Smarcel     have called single_step() to transmute the step request into a
552130812Smarcel     continue request (by setting breakpoints on all possible successor
553130812Smarcel     instructions), so we don't have to worry about that here.  */
554130812Smarcel
555130812Smarcel  ptrace (func, pid, (PTRACE_ARG3_TYPE) 1, target_signal_to_host (signal));
556130812Smarcel
557130812Smarcel  if (errno)
558130812Smarcel    perror_with_name ("ptrace");
559130812Smarcel}
560130812Smarcel
561130812Smarcel/* Convert a Lynx process ID to a string.  Returns the string in a static
562130812Smarcel   buffer.  */
563130812Smarcel
564130812Smarcelchar *
565130812Smarcelchild_pid_to_str (ptid_t ptid)
566130812Smarcel{
567130812Smarcel  static char buf[40];
568130812Smarcel
569130812Smarcel  sprintf (buf, "process %d thread %d", PIDGET (ptid), TIDGET (ptid));
570130812Smarcel
571130812Smarcel  return buf;
572130812Smarcel}
573130812Smarcel
574130812Smarcel/* Extract the register values out of the core file and store
575130812Smarcel   them where `read_register' will find them.
576130812Smarcel
577130812Smarcel   CORE_REG_SECT points to the register values themselves, read into memory.
578130812Smarcel   CORE_REG_SIZE is the size of that area.
579130812Smarcel   WHICH says which set of registers we are handling (0 = int, 2 = float
580130812Smarcel   on machines where they are discontiguous).
581130812Smarcel   REG_ADDR is the offset from u.u_ar0 to the register values relative to
582130812Smarcel   core_reg_sect.  This is used with old-fashioned core files to
583130812Smarcel   locate the registers in a large upage-plus-stack ".reg" section.
584130812Smarcel   Original upage address X is at location core_reg_sect+x+reg_addr.
585130812Smarcel */
586130812Smarcel
587130812Smarcelstatic void
588130812Smarcelfetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
589130812Smarcel		      CORE_ADDR reg_addr)
590130812Smarcel{
591130812Smarcel  struct st_entry s;
592130812Smarcel  unsigned int regno;
593130812Smarcel
594130812Smarcel  for (regno = 0; regno < NUM_REGS; regno++)
595130812Smarcel    if (regmap[regno] != -1)
596130812Smarcel      supply_register (regno, core_reg_sect + offsetof (st_t, ec)
597130812Smarcel		       + regmap[regno]);
598130812Smarcel
599130812Smarcel#ifdef SPARC
600130812Smarcel/* Fetching this register causes all of the I & L regs to be read from the
601130812Smarcel   stack and validated.  */
602130812Smarcel
603130812Smarcel  fetch_inferior_registers (I0_REGNUM);
604130812Smarcel#endif
605130812Smarcel}
606130812Smarcel
607130812Smarcel
608130812Smarcel/* Register that we are able to handle lynx core file formats.
609130812Smarcel   FIXME: is this really bfd_target_unknown_flavour? */
610130812Smarcel
611130812Smarcelstatic struct core_fns lynx_core_fns =
612130812Smarcel{
613130812Smarcel  bfd_target_unknown_flavour,		/* core_flavour */
614130812Smarcel  default_check_format,			/* check_format */
615130812Smarcel  default_core_sniffer,			/* core_sniffer */
616130812Smarcel  fetch_core_registers,			/* core_read_registers */
617130812Smarcel  NULL					/* next */
618130812Smarcel};
619130812Smarcel
620130812Smarcelvoid
621130812Smarcel_initialize_core_lynx (void)
622130812Smarcel{
623130812Smarcel  add_core_fns (&lynx_core_fns);
624130812Smarcel}
625