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