xref: /openbsd/gnu/usr.bin/binutils/gdb/lynx-nat.c (revision 63addd46)
1 /* Native-dependent code for LynxOS.
2 
3    Copyright 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2003 Free
4    Software Foundation, Inc.
5 
6    This file is part of GDB.
7 
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.
12 
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.
17 
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
20    Foundation, Inc., 59 Temple Place - Suite 330,
21    Boston, MA 02111-1307, USA.  */
22 
23 #include "defs.h"
24 #include "frame.h"
25 #include "inferior.h"
26 #include "target.h"
27 #include "gdbcore.h"
28 #include "regcache.h"
29 
30 #include <sys/ptrace.h>
31 #Include "gdb_wait.h"
32 #include <sys/fpp.h>
33 
34 static unsigned long registers_addr (int pid);
35 static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
36 
37 #define X(ENTRY)(offsetof(struct econtext, ENTRY))
38 
39 #ifdef I386
40 /* Mappings from tm-i386v.h */
41 
42 static int regmap[] =
43 {
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
60 				   that they are useful. */
61 };
62 #endif /* I386 */
63 
64 #ifdef M68K
65 /* Mappings from tm-m68k.h */
66 
67 static int regmap[] =
68 {
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 */
102 };
103 #endif /* M68K */
104 
105 #ifdef SPARC
106 /* Mappings from tm-sparc.h */
107 
108 #define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
109 
110 static int regmap[] =
111 {
112   -1,				/* g0 */
113   X (g1),
114   X (g2),
115   X (g3),
116   X (g4),
117   -1,				/* g5->g7 aren't saved by Lynx */
118   -1,
119   -1,
120 
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 */
174   -1,				/* cpsr */
175 };
176 #endif /* SPARC */
177 
178 #ifdef rs6000
179 
180 static int regmap[] =
181 {
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 */
255 };
256 
257 #endif /* rs6000 */
258 
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 
264 static unsigned long
registers_addr(int pid)265 registers_addr (int pid)
266 {
267   CORE_ADDR stblock;
268   int ecpoff = offsetof (st_t, ecp);
269   CORE_ADDR ecp;
270 
271   errno = 0;
272   stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE) 0,
273 				0);
274   if (errno)
275     perror_with_name ("ptrace(PTRACE_THREADUSER)");
276 
277   ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) ecpoff,
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 
289 void
fetch_inferior_registers(int regno)290 fetch_inferior_registers (int regno)
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 
304   ecp = registers_addr (PIDGET (inferior_ptid));
305 
306   {
307     char buf[MAX_REGISTER_SIZE];
308     for (regno = reglo; regno <= reghi; regno++)
309       {
310 	int ptrace_fun = PTRACE_PEEKTHREAD;
311 
312 #ifdef M68K
313 	ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
314 #endif
315 
316 	for (i = 0; i < register_size (current_gdbarch, regno); i += sizeof (int))
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 	  }
328 	regcache_raw_supply (current_regcache, regno, buf);
329       }
330   }
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 
337 void
store_inferior_registers(int regno)338 store_inferior_registers (int regno)
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 
352   ecp = registers_addr (PIDGET (inferior_ptid));
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 
365       for (i = 0; i < register_size (current_gdbarch, regno); i += sizeof (int))
366 	{
367 	  unsigned int reg;
368 
369 	  reg = *(unsigned int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno) + i];
370 
371 	  errno = 0;
372 	  ptrace (ptrace_fun, PIDGET (inferior_ptid),
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 
384 ptid_t
child_wait(ptid_t ptid,struct target_waitstatus * ourstatus)385 child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
386 {
387   int save_errno;
388   int thread;
389   union wait status;
390   int pid;
391 
392   while (1)
393     {
394       int sig;
395 
396       set_sigint_trap ();	/* Causes SIGINT to be passed on to the
397 				   attached process. */
398       pid = wait (&status);
399 
400       save_errno = errno;
401 
402       clear_sigint_trap ();
403 
404       if (pid == -1)
405 	{
406 	  if (save_errno == EINTR)
407 	    continue;
408 	  fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
409 			      safe_strerror (save_errno));
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 
416       if (pid != PIDGET (inferior_ptid))	/* Some other process?!? */
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
422          resort to this hack.  */
423 
424       if (TIDGET (inferior_ptid) == 0 && thread != 0)
425 	{
426 	  inferior_ptid = MERGEPID (PIDGET (inferior_ptid), thread);
427 	  add_thread (inferior_ptid);
428 	}
429 
430       ptid = BUILDPID (pid, thread);
431 
432       /* We've become a single threaded process again.  */
433       if (thread == 0)
434 	inferior_ptid = ptid;
435 
436       /* Check for thread creation.  */
437       if (WIFSTOPPED (status)
438 	  && WSTOPSIG (status) == SIGTRAP
439 	  && !in_thread_list (ptid))
440 	{
441 	  int realsig;
442 
443 	  realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid),
444 	                    (PTRACE_ARG3_TYPE) 0, 0);
445 
446 	  if (realsig == SIGNEWTHREAD)
447 	    {
448 	      /* It's a new thread notification.  We don't want to much with
449 	         realsig -- the code in wait_for_inferior expects SIGTRAP. */
450 	      ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
451 	      ourstatus->value.sig = TARGET_SIGNAL_0;
452 	      return ptid;
453 	    }
454 	  else
455 	    error ("Signal for unknown thread was not SIGNEWTHREAD");
456 	}
457 
458       /* Check for thread termination.  */
459       else if (WIFSTOPPED (status)
460 	       && WSTOPSIG (status) == SIGTRAP
461 	       && in_thread_list (ptid))
462 	{
463 	  int realsig;
464 
465 	  realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid),
466 	                    (PTRACE_ARG3_TYPE) 0, 0);
467 
468 	  if (realsig == SIGTHREADEXIT)
469 	    {
470 	      ptrace (PTRACE_CONT, PIDGET (ptid), (PTRACE_ARG3_TYPE) 0, 0);
471 	      continue;
472 	    }
473 	}
474 
475 #ifdef SPARC
476       /* SPARC Lynx uses an byte reversed wait status; we must use the
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>.  */
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 
501       return ptid;
502     }
503 }
504 
505 /* Return nonzero if the given thread is still alive.  */
506 int
child_thread_alive(ptid_t ptid)507 child_thread_alive (ptid_t ptid)
508 {
509   int pid = PIDGET (ptid);
510 
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 
527 void
child_resume(ptid_t ptid,int step,enum target_signal signal)528 child_resume (ptid_t ptid, int step, enum target_signal signal)
529 {
530   int func;
531   int pid = PIDGET (ptid);
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     {
539       pid = PIDGET (inferior_ptid);
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 
564 char *
child_pid_to_str(ptid_t ptid)565 child_pid_to_str (ptid_t ptid)
566 {
567   static char buf[40];
568 
569   sprintf (buf, "process %d thread %d", PIDGET (ptid), TIDGET (ptid));
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
580    on machines where they are discontiguous).
581    REG_ADDR is the offset from u.u_ar0 to the register values relative to
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.
585  */
586 
587 static void
fetch_core_registers(char * core_reg_sect,unsigned core_reg_size,int which,CORE_ADDR reg_addr)588 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
589 		      CORE_ADDR reg_addr)
590 {
591   struct st_entry s;
592   unsigned int regno;
593 
594   for (regno = 0; regno < NUM_REGS; regno++)
595     if (regmap[regno] != -1)
596       regcache_raw_supply (current_regcache, regno,
597 			   core_reg_sect + offsetof (st_t, ec) + regmap[regno]);
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 }
606 
607 
608 /* Register that we are able to handle lynx core file formats.
609    FIXME: is this really bfd_target_unknown_flavour? */
610 
611 static struct core_fns lynx_core_fns =
612 {
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 */
618 };
619 
620 void
_initialize_core_lynx(void)621 _initialize_core_lynx (void)
622 {
623   deprecated_add_core_fns (&lynx_core_fns);
624 }
625