Mon Aug 2 11:30:57 1993 Stu Grossman (grossman at cygnus.com)
[deliverable/binutils-gdb.git] / gdb / i386lynx-nat.c
1 /* Native-dependent code for Lynx running on i386's, for GDB.
2 Copyright 1988, 1989, 1991, 1992, 1993
3 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include "defs.h"
22 #include "frame.h"
23 #include "inferior.h"
24 #include "gdbcore.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 /* Extract the register values out of the core file and store
188 them where `read_register' will find them.
189
190 CORE_REG_SECT points to the register values themselves, read into memory.
191 CORE_REG_SIZE is the size of that area.
192 WHICH says which set of registers we are handling (0 = int, 2 = float
193 on machines where they are discontiguous).
194 REG_ADDR is the offset from u.u_ar0 to the register values relative to
195 core_reg_sect. This is used with old-fashioned core files to
196 locate the registers in a large upage-plus-stack ".reg" section.
197 Original upage address X is at location core_reg_sect+x+reg_addr.
198 */
199
200 void
201 fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
202 char *core_reg_sect;
203 unsigned core_reg_size;
204 int which;
205 unsigned reg_addr;
206 {
207 struct st_entry s;
208 unsigned int regno, addr;
209
210 for (regno = 0; regno < NUM_REGS; regno++)
211 {
212 addr = register_addr (regno, (char *) &s.ec - (char *) &s);
213 supply_register (regno, core_reg_sect + addr);
214 }
215 }
216
217 /* Wait for child to do something. Return pid of child, or -1 in case
218 of error; store status through argument pointer STATUS. */
219
220 int
221 child_wait (status)
222 int *status;
223 {
224 int pid;
225 int save_errno;
226 int thread;
227
228 while (1)
229 {
230 int sig;
231
232 if (attach_flag)
233 set_sigint_trap(); /* Causes SIGINT to be passed on to the
234 attached process. */
235 pid = wait (status);
236 save_errno = errno;
237
238 if (attach_flag)
239 clear_sigint_trap();
240
241 if (pid == -1)
242 {
243 if (save_errno == EINTR)
244 continue;
245 fprintf (stderr, "Child process unexpectedly missing: %s.\n",
246 safe_strerror (save_errno));
247 *status = 42; /* Claim it exited with signal 42 */
248 return -1;
249 }
250
251 if (pid != PIDGET (inferior_pid)) /* Some other process?!? */
252 continue;
253
254 /* thread = WIFTID (*status);*/
255 thread = *status >> 16;
256
257 /* Initial thread value can only be acquired via wait, so we have to
258 resort to this hack. */
259
260 if (TIDGET (inferior_pid) == 0)
261 {
262 inferior_pid = BUILDPID (inferior_pid, thread);
263 add_thread (inferior_pid);
264 }
265
266 pid = BUILDPID (pid, thread);
267
268 return pid;
269 }
270 }
271
272 /* Return the PC of the caller from the call frame. Assumes the subr prologue
273 has already been executed, and the frame pointer setup. If this is the
274 outermost frame, we check to see if we are in a system call by examining the
275 previous instruction. If so, then the return PC is actually at SP+4 because
276 system calls use a different calling sequence. */
277
278 CORE_ADDR
279 i386lynx_saved_pc_after_call (frame)
280 struct frame_info *frame;
281 {
282 char opcode[7];
283 static const char call_inst[] = {0x9a, 0, 0, 0, 0, 8, 0}; /* lcall 0x8,0x0 */
284
285 read_memory (frame->pc - 7, opcode, 7);
286 if (memcmp (opcode, call_inst, 7) == 0)
287 return read_memory_integer (read_register (SP_REGNUM) + 4, 4);
288
289 return read_memory_integer (read_register (SP_REGNUM), 4);
290 }
291
292 /* Convert a Lynx process ID to a string. Returns the string in a static
293 buffer. */
294
295 char *
296 i386lynx_pid_to_str (pid)
297 int pid;
298 {
299 static char buf[40];
300
301 sprintf (buf, "process %d thread %d", PIDGET (pid), TIDGET (pid));
302
303 return buf;
304 }
This page took 0.035317 seconds and 4 git commands to generate.