1 /* Native-dependent code for LynxOS.
2 Copyright 1993 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
25 #include <sys/ptrace.h>
26 #include "/usr/include/sys/wait.h"
28 static unsigned long registers_addr
PARAMS ((int pid
));
30 #define X(ENTRY)(offsetof(struct econtext, ENTRY))
33 /* Mappings from tm-i386v.h */
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. */
58 /* Mappings from tm-m68k.h */
77 offsetof (st_t
, usp
) - offsetof (st_t
, ec
), /* sp */
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 */
90 X(fcregs
[0]), /* fpcontrol */
91 X(fcregs
[1]), /* fpstatus */
92 X(fcregs
[2]), /* fpiaddr */
94 X(fault
), /* fpflags */
98 /* Return the offset relative to the start of the per-thread data to the
99 saved context block. */
106 int ecpoff
= offsetof(st_t
, ecp
);
110 stblock
= (CORE_ADDR
) ptrace (PTRACE_THREADUSER
, pid
, (PTRACE_ARG3_TYPE
)0,
113 perror_with_name ("registers_addr(PTRACE_THREADUSER)");
115 ecp
= (CORE_ADDR
) ptrace (PTRACE_PEEKTHREAD
, pid
, (PTRACE_ARG3_TYPE
)ecpoff
,
118 perror_with_name ("registers_addr(PTRACE_PEEKTHREAD)");
120 return ecp
- stblock
;
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. */
128 fetch_inferior_registers (regno
)
138 reghi
= NUM_REGS
- 1;
141 reglo
= reghi
= regno
;
143 ecp
= registers_addr (inferior_pid
);
145 for (regno
= reglo
; regno
<= reghi
; regno
++)
147 char buf
[MAX_REGISTER_RAW_SIZE
];
148 int ptrace_fun
= PTRACE_PEEKTHREAD
;
150 #ifdef PTRACE_PEEKUSP
151 ptrace_fun
= regno
== SP_REGNUM
? PTRACE_PEEKUSP
: PTRACE_PEEKTHREAD
;
154 for (i
= 0; i
< REGISTER_RAW_SIZE (regno
); i
+= sizeof (int))
159 reg
= ptrace (ptrace_fun
, inferior_pid
,
160 (PTRACE_ARG3_TYPE
) (ecp
+ regmap
[regno
] + i
), 0);
162 perror_with_name ("fetch_inferior_registers(ptrace)");
164 *(int *)&buf
[i
] = reg
;
166 supply_register (regno
, buf
);
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). */
175 store_inferior_registers (regno
)
185 reghi
= NUM_REGS
- 1;
188 reglo
= reghi
= regno
;
190 ecp
= registers_addr (inferior_pid
);
192 for (regno
= reglo
; regno
<= reghi
; regno
++)
194 int ptrace_fun
= PTRACE_POKEUSER
;
196 #ifdef PTRACE_POKEUSP
197 ptrace_fun
= regno
== SP_REGNUM
? PTRACE_POKEUSP
: PTRACE_POKEUSER
;
200 for (i
= 0; i
< REGISTER_RAW_SIZE (regno
); i
+= sizeof (int))
204 reg
= *(unsigned int *)®isters
[REGISTER_BYTE (regno
) + i
];
207 ptrace (ptrace_fun
, inferior_pid
,
208 (PTRACE_ARG3_TYPE
) (ecp
+ regmap
[regno
] + i
), reg
);
210 perror_with_name ("PTRACE_POKEUSER");
215 /* Wait for child to do something. Return pid of child, or -1 in case
216 of error; store status through argument pointer OURSTATUS. */
219 child_wait (pid
, status
)
221 struct target_waitstatus
*ourstatus
;
231 set_sigint_trap(); /* Causes SIGINT to be passed on to the
241 if (save_errno
== EINTR
)
243 fprintf_unfiltered (gdb_stderr
, "Child process unexpectedly missing: %s.\n",
244 safe_strerror (save_errno
));
245 /* Claim it exited with unknown signal. */
246 ourstatus
->kind
= TARGET_WAITKIND_SIGNALLED
;
247 ourstatus
->value
.sig
= TARGET_SIGNAL_UNKNOWN
;
251 if (pid
!= PIDGET (inferior_pid
)) /* Some other process?!? */
254 /* thread = WIFTID (*status);*/
255 thread
= *status
>> 16;
257 /* Initial thread value can only be acquired via wait, so we have to
258 resort to this hack. */
260 if (TIDGET (inferior_pid
) == 0)
262 inferior_pid
= BUILDPID (inferior_pid
, thread
);
263 add_thread (inferior_pid
);
266 pid
= BUILDPID (pid
, thread
);
268 store_waitstatus (ourstatus
, status
);
274 /* Convert a Lynx process ID to a string. Returns the string in a static
278 lynx_pid_to_str (pid
)
283 sprintf (buf
, "process %d thread %d", PIDGET (pid
), TIDGET (pid
));
288 /* Extract the register values out of the core file and store
289 them where `read_register' will find them.
291 CORE_REG_SECT points to the register values themselves, read into memory.
292 CORE_REG_SIZE is the size of that area.
293 WHICH says which set of registers we are handling (0 = int, 2 = float
294 on machines where they are discontiguous).
295 REG_ADDR is the offset from u.u_ar0 to the register values relative to
296 core_reg_sect. This is used with old-fashioned core files to
297 locate the registers in a large upage-plus-stack ".reg" section.
298 Original upage address X is at location core_reg_sect+x+reg_addr.
302 fetch_core_registers (core_reg_sect
, core_reg_size
, which
, reg_addr
)
304 unsigned core_reg_size
;
311 for (regno
= 0; regno
< NUM_REGS
; regno
++)
312 supply_register (regno
, core_reg_sect
+ offsetof (st_t
, ec
)