Keep COPYING.NEWLIB if keep-newlib.
[deliverable/binutils-gdb.git] / gdb / i386lynx-nat.c
1 <<<<<<< 2.6 is dead >>>>>>>
2 /* Native-dependent code for Lynx running on i386's, for GDB.
3 Copyright 1988, 1989, 1991, 1992, 1993
4 Free 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22 #include "defs.h"
23 #include "frame.h"
24 #include "inferior.h"
25 #include "target.h"
26
27 #include <sys/ptrace.h>
28 #include "/usr/include/sys/wait.h"
29
30 /* these values indicate the offset of the named register in the econtext
31 structure */
32
33 #define EAX 10
34 #define ECX 9
35 #define EDX 8
36 #define EBX 7
37 #define ESP 16
38 #define EBP 5
39 #define ESI 4
40 #define EDI 3
41 #define EIP 13
42 #define EFL 15
43 #define CS 14
44 #define SS 17
45 #define DS 2
46 #define ES 1
47
48 /* Currently these are not being used. So set them to 0 */
49
50 #define FS 0
51 #define GS 0
52
53 /* this table must line up with REGISTER_NAMES in m-i386.h */
54 static unsigned int regmap[] =
55 {
56 EAX, ECX, EDX, EBX,
57 ESP, EBP, ESI, EDI,
58 EIP, EFL, CS, SS,
59 DS, ES, FS, GS,
60 };
61
62 /* Return the address in the core dump or inferior of register REGNO.
63 BLOCKEND is the address of the econtext structure */
64
65 static unsigned int
66 register_addr (regno, blockend)
67 int regno, blockend;
68 {
69 if (regno < 0 || regno >= NUM_REGS)
70 error ("Invalid register number %d.", regno);
71
72 return (blockend + regmap[regno] * sizeof (long));
73 }
74
75 /* Fetch one register. */
76
77 static void
78 fetch_register (regno, offset, bpid)
79 int regno, bpid;
80 unsigned int offset;
81 {
82 unsigned int regaddr;
83 char buf[MAX_REGISTER_RAW_SIZE];
84 char mess[128]; /* For messages */
85 int i;
86
87 regaddr = register_addr (regno, offset);
88 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
89 {
90 errno = 0;
91 *(int *) &buf[i] = ptrace (PTRACE_PEEKTHREAD, bpid,
92 (PTRACE_ARG3_TYPE) regaddr, 0);
93 regaddr += sizeof (int);
94 if (errno != 0)
95 {
96 sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno);
97 perror_with_name (mess);
98 }
99 }
100 supply_register (regno, buf);
101 }
102
103 /* Store our register values back into the inferior.
104 If REGNO is -1, do this for all registers.
105 Otherwise, REGNO specifies which register (so we can save time). */
106
107 static void
108 store_register (regno, offset, bpid)
109 int regno, bpid;
110 unsigned int offset;
111 {
112 unsigned int regaddr;
113 char mess[128];
114 extern char registers[];
115 int i;
116
117 regaddr = register_addr (regno, offset);
118 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
119 {
120 errno = 0;
121 ptrace (PTRACE_POKEUSER, bpid, (PTRACE_ARG3_TYPE) regaddr,
122 *(int *) &registers[REGISTER_BYTE (regno) + i]);
123 if (errno != 0)
124 {
125 sprintf (mess, "writing register number %d(%d)", regno, i);
126 perror_with_name (mess);
127 }
128 regaddr += sizeof(int);
129 }
130 }
131
132 /* return an offset for use with register_addr() */
133
134 static unsigned int
135 fetch_offset (pid)
136 int pid;
137 {
138 struct st_entry s;
139 unsigned int specpage_off, offset = (char *) &s.ecp - (char *) &s;
140
141 errno = 0;
142 specpage_off = ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE) 0, 0);
143 if (errno != 0)
144 perror_with_name ("ptrace");
145 errno = 0;
146 offset = ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) offset, 0)
147 - specpage_off;
148 if (errno != 0)
149 perror_with_name ("ptrace");
150 return offset;
151 }
152
153 /* Fetch all registers, or just one, from the child process. */
154
155 void
156 fetch_inferior_registers (regno)
157 int regno;
158 {
159 unsigned int offset = fetch_offset (inferior_pid);
160
161 if (regno == -1)
162 {
163 for (regno = 0; regno < NUM_REGS; regno++)
164 fetch_register (regno, offset, inferior_pid);
165 }
166 else
167 fetch_register (regno, offset, inferior_pid);
168 }
169
170 /* Store all registers, or just one, to the child process. */
171
172 void
173 store_inferior_registers (regno)
174 int regno;
175 {
176 unsigned int offset = fetch_offset (inferior_pid);
177
178 if (regno == -1)
179 {
180 for (regno = 0; regno < NUM_REGS; regno++)
181 store_register (regno, offset, inferior_pid);
182 }
183 else
184 store_register (regno, offset, inferior_pid);
185 }
186
187 /* Wait for child to do something. Return pid of child, or -1 in case
188 of error; store status through argument pointer STATUS. */
189
190 int
191 child_wait (pid, status)
192 int pid;
193 int *status;
194 {
195 int save_errno;
196 int thread;
197
198 while (1)
199 {
200 int sig;
201
202 if (attach_flag)
203 set_sigint_trap(); /* Causes SIGINT to be passed on to the
204 attached process. */
205 pid = wait (status);
206 save_errno = errno;
207
208 if (attach_flag)
209 clear_sigint_trap();
210
211 if (pid == -1)
212 {
213 if (save_errno == EINTR)
214 continue;
215 fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
216 safe_strerror (save_errno));
217 *status = 42; /* Claim it exited with signal 42 */
218 return -1;
219 }
220
221 if (pid != PIDGET (inferior_pid)) /* Some other process?!? */
222 continue;
223
224 /* thread = WIFTID (*status);*/
225 thread = *status >> 16;
226
227 /* Initial thread value can only be acquired via wait, so we have to
228 resort to this hack. */
229
230 if (TIDGET (inferior_pid) == 0)
231 {
232 inferior_pid = BUILDPID (inferior_pid, thread);
233 add_thread (inferior_pid);
234 }
235
236 pid = BUILDPID (pid, thread);
237
238 return pid;
239 }
240 }
241
242 /* Convert a Lynx process ID to a string. Returns the string in a static
243 buffer. */
244
245 char *
246 i386lynx_pid_to_str (pid)
247 int pid;
248 {
249 static char buf[40];
250
251 sprintf (buf, "process %d thread %d", PIDGET (pid), TIDGET (pid));
252
253 return buf;
254 }
255
256 /* Extract the register values out of the core file and store
257 them where `read_register' will find them.
258
259 CORE_REG_SECT points to the register values themselves, read into memory.
260 CORE_REG_SIZE is the size of that area.
261 WHICH says which set of registers we are handling (0 = int, 2 = float
262 on machines where they are discontiguous).
263 REG_ADDR is the offset from u.u_ar0 to the register values relative to
264 core_reg_sect. This is used with old-fashioned core files to
265 locate the registers in a large upage-plus-stack ".reg" section.
266 Original upage address X is at location core_reg_sect+x+reg_addr.
267 */
268
269 void
270 fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
271 char *core_reg_sect;
272 unsigned core_reg_size;
273 int which;
274 unsigned reg_addr;
275 {
276 struct st_entry s;
277 unsigned int regno, addr;
278
279 for (regno = 0; regno < NUM_REGS; regno++)
280 {
281 addr = register_addr (regno, (char *) &s.ec - (char *) &s);
282 supply_register (regno, core_reg_sect + addr);
283 }
284 }
This page took 0.047436 seconds and 4 git commands to generate.