use remote-utils facilities for baud_rate
[deliverable/binutils-gdb.git] / gdb / i386lynx-nat.c
CommitLineData
25286543 1/* Native-dependent code for Lynx running on i386's, for GDB.
da0baf42
SG
2 Copyright 1988, 1989, 1991, 1992, 1993
3 Free Software Foundation, Inc.
25286543
SG
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, 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 */
54static 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
65static unsigned int
66register_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
77static void
78fetch_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
107static void
108store_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
134static unsigned int
135fetch_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
155void
156fetch_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
172void
173store_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
200void
201fetch_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
220int
221child_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
278CORE_ADDR
279i386lynx_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
295char *
296i386lynx_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.040467 seconds and 4 git commands to generate.