]> Git Repo - binutils.git/blob - gdb/i386lynx-nat.c
comment change
[binutils.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.044178 seconds and 4 git commands to generate.