* Makefile.in: Add i386lynx-tdep to the right places.
[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 static struct target_ops lynx_core_ops;
54
55 /* this table must line up with REGISTER_NAMES in m-i386.h */
56 static unsigned int regmap[] =
57 {
58 EAX, ECX, EDX, EBX,
59 ESP, EBP, ESI, EDI,
60 EIP, EFL, CS, SS,
61 DS, ES, FS, GS,
62 };
63
64 /* Return the address in the core dump or inferior of register REGNO.
65 BLOCKEND is the address of the econtext structure */
66
67 static unsigned int
68 register_addr (regno, blockend)
69 int regno, blockend;
70 {
71 if (regno < 0 || regno >= NUM_REGS)
72 error ("Invalid register number %d.", regno);
73
74 return (blockend + regmap[regno] * sizeof (long));
75 }
76
77 /* Fetch one register. */
78
79 static void
80 fetch_register (regno, offset, bpid)
81 int regno, bpid;
82 unsigned int offset;
83 {
84 unsigned int regaddr;
85 char buf[MAX_REGISTER_RAW_SIZE];
86 char mess[128]; /* For messages */
87 int i;
88
89 regaddr = register_addr (regno, offset);
90 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
91 {
92 errno = 0;
93 *(int *) &buf[i] = ptrace (PTRACE_PEEKTHREAD, bpid,
94 (PTRACE_ARG3_TYPE) regaddr, 0);
95 regaddr += sizeof (int);
96 if (errno != 0)
97 {
98 sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno);
99 perror_with_name (mess);
100 }
101 }
102 supply_register (regno, buf);
103 }
104
105 /* Store our register values back into the inferior.
106 If REGNO is -1, do this for all registers.
107 Otherwise, REGNO specifies which register (so we can save time). */
108
109 static void
110 store_register (regno, offset, bpid)
111 int regno, bpid;
112 unsigned int offset;
113 {
114 unsigned int regaddr;
115 char mess[128];
116 extern char registers[];
117 int i;
118
119 regaddr = register_addr (regno, offset);
120 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
121 {
122 errno = 0;
123 ptrace (PTRACE_POKEUSER, bpid, (PTRACE_ARG3_TYPE) regaddr,
124 *(int *) &registers[REGISTER_BYTE (regno) + i]);
125 if (errno != 0)
126 {
127 sprintf (mess, "writing register number %d(%d)", regno, i);
128 perror_with_name (mess);
129 }
130 regaddr += sizeof(int);
131 }
132 }
133
134 /* return an offset for use with register_addr() */
135
136 static unsigned int
137 fetch_offset (pid)
138 int pid;
139 {
140 struct st_entry s;
141 unsigned int specpage_off, offset = (char *) &s.ecp - (char *) &s;
142
143 errno = 0;
144 specpage_off = ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE) 0, 0);
145 if (errno != 0)
146 perror_with_name ("ptrace");
147 errno = 0;
148 offset = ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) offset, 0)
149 - specpage_off;
150 if (errno != 0)
151 perror_with_name ("ptrace");
152 return offset;
153 }
154
155 /* Fetch all registers, or just one, from the child process. */
156
157 void
158 fetch_inferior_registers (regno)
159 int regno;
160 {
161 unsigned int offset = fetch_offset (inferior_pid);
162
163 if (regno == -1)
164 {
165 for (regno = 0; regno < NUM_REGS; regno++)
166 fetch_register (regno, offset, inferior_pid);
167 }
168 else
169 fetch_register (regno, offset, inferior_pid);
170 }
171
172 /* Store all registers, or just one, to the child process. */
173
174 void
175 store_inferior_registers (regno)
176 int regno;
177 {
178 unsigned int offset = fetch_offset (inferior_pid);
179
180 if (regno == -1)
181 {
182 for (regno = 0; regno < NUM_REGS; regno++)
183 store_register (regno, offset, inferior_pid);
184 }
185 else
186 store_register (regno, offset, inferior_pid);
187 }
188
189 /* Wait for child to do something. Return pid of child, or -1 in case
190 of error; store status through argument pointer STATUS. */
191
192 int
193 child_wait (status)
194 int *status;
195 {
196 int pid;
197 int save_errno;
198 int thread;
199
200 while (1)
201 {
202 int sig;
203
204 if (attach_flag)
205 set_sigint_trap(); /* Causes SIGINT to be passed on to the
206 attached process. */
207 pid = wait (status);
208 save_errno = errno;
209
210 if (attach_flag)
211 clear_sigint_trap();
212
213 if (pid == -1)
214 {
215 if (save_errno == EINTR)
216 continue;
217 fprintf (stderr, "Child process unexpectedly missing: %s.\n",
218 safe_strerror (save_errno));
219 *status = 42; /* Claim it exited with signal 42 */
220 return -1;
221 }
222
223 if (pid != PIDGET (inferior_pid)) /* Some other process?!? */
224 continue;
225
226 /* thread = WIFTID (*status);*/
227 thread = *status >> 16;
228
229 /* Initial thread value can only be acquired via wait, so we have to
230 resort to this hack. */
231
232 if (TIDGET (inferior_pid) == 0)
233 {
234 inferior_pid = BUILDPID (inferior_pid, thread);
235 add_thread (inferior_pid);
236 }
237
238 pid = BUILDPID (pid, thread);
239
240 return pid;
241 }
242 }
243
244 /* Convert a Lynx process ID to a string. Returns the string in a static
245 buffer. */
246
247 char *
248 i386lynx_pid_to_str (pid)
249 int pid;
250 {
251 static char buf[40];
252
253 sprintf (buf, "process %d thread %d", PIDGET (pid), TIDGET (pid));
254
255 return buf;
256 }
257
258 /* Extract the register values out of the core file and store
259 them where `read_register' will find them.
260
261 CORE_REG_SECT points to the register values themselves, read into memory.
262 CORE_REG_SIZE is the size of that area.
263 WHICH says which set of registers we are handling (0 = int, 2 = float
264 on machines where they are discontiguous).
265 REG_ADDR is the offset from u.u_ar0 to the register values relative to
266 core_reg_sect. This is used with old-fashioned core files to
267 locate the registers in a large upage-plus-stack ".reg" section.
268 Original upage address X is at location core_reg_sect+x+reg_addr.
269 */
270
271 void
272 fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
273 char *core_reg_sect;
274 unsigned core_reg_size;
275 int which;
276 unsigned reg_addr;
277 {
278 struct st_entry s;
279 unsigned int regno, addr;
280
281 for (regno = 0; regno < NUM_REGS; regno++)
282 {
283 addr = register_addr (regno, (char *) &s.ec - (char *) &s);
284 supply_register (regno, core_reg_sect + addr);
285 }
286 }
287
288 #if 0
289
290 /* Discard all vestiges of any previous core file
291 and mark data and stack spaces as empty. */
292
293 /* ARGSUSED */
294 static void
295 lynx_core_close (quitting)
296 int quitting;
297 {
298 if (core_bfd)
299 {
300 free (bfd_get_filename (core_bfd));
301 bfd_close (core_bfd);
302 core_bfd = NULL;
303
304 if (core_ops.to_sections)
305 {
306 free ((PTR)lynx_core_ops.to_sections);
307 lynx_core_ops.to_sections = NULL;
308 lynx_core_ops.to_sections_end = NULL;
309 }
310 }
311 }
312
313 /* This routine opens and sets up the core file bfd */
314
315 static void
316 lynx_core_open (filename, from_tty)
317 char *filename;
318 int from_tty;
319 {
320 const char *p;
321 int siggy;
322 struct cleanup *old_chain;
323 char *temp;
324 bfd *temp_bfd;
325 int ontop;
326 int scratch_chan;
327
328 target_preopen (from_tty);
329 if (!filename)
330 {
331 error (core_bfd ?
332 "No core file specified. (Use `detach' to stop debugging a core file.)"
333 : "No core file specified.");
334 }
335
336 filename = tilde_expand (filename);
337 if (filename[0] != '/')
338 {
339 temp = concat (current_directory, "/", filename, NULL);
340 free (filename);
341 filename = temp;
342 }
343
344 old_chain = make_cleanup (free, filename);
345
346 scratch_chan = open (filename, write_files? O_RDWR: O_RDONLY, 0);
347 if (scratch_chan < 0)
348 perror_with_name (filename);
349
350 temp_bfd = bfd_fdopenr (filename, NULL, scratch_chan);
351 if (temp_bfd == NULL)
352 perror_with_name (filename);
353
354 if (!bfd_check_format (temp_bfd, bfd_core))
355 {
356 /* Do it after the err msg */
357 make_cleanup (bfd_close, temp_bfd);
358 error ("\"%s\" is not a core dump: %s", filename, bfd_errmsg(bfd_error));
359 }
360
361 /* Looks semi-reasonable. Toss the old core file and work on the new. */
362
363 discard_cleanups (old_chain); /* Don't free filename any more */
364 unpush_target (&core_ops);
365 core_bfd = temp_bfd;
366 old_chain = make_cleanup (core_close, core_bfd);
367
368 validate_files ();
369
370 /* Find the data section */
371 if (build_section_table (core_bfd, &core_ops.to_sections,
372 &core_ops.to_sections_end))
373 error ("Can't find sections in `%s': %s", bfd_get_filename(core_bfd),
374 bfd_errmsg (bfd_error));
375
376 ontop = !push_target (&core_ops);
377 discard_cleanups (old_chain);
378
379 p = bfd_core_file_failing_command (core_bfd);
380 if (p)
381 printf_filtered ("Core was generated by `%s'.\n", p);
382
383 siggy = bfd_core_file_failing_signal (core_bfd);
384 if (siggy > 0)
385 printf_filtered ("Program terminated with signal %d, %s.\n", siggy,
386 safe_strsignal (siggy));
387
388 /* Locate all of the thread register sections. They have names like .regxx,
389 where xx is the thread-id. */
390
391 bfd_map_over_sections (core_bfd, grok_register_sections,
392
393 if (ontop)
394 {
395 /* Fetch all registers from core file */
396 target_fetch_registers (-1);
397
398 /* Now, set up the frame cache, and print the top of stack */
399 set_current_frame (create_new_frame (read_fp (),
400 read_pc ()));
401 select_frame (get_current_frame (), 0);
402 print_stack_frame (selected_frame, selected_frame_level, 1);
403 }
404 else
405 {
406 warning (
407 "you won't be able to access this core file until you terminate\n\
408 your %s; do ``info files''", current_target->to_longname);
409 }
410 }
411
412 static void
413 lynx_core_detach (args, from_tty)
414 char *args;
415 int from_tty;
416 {
417 if (args)
418 error ("Too many arguments");
419 unpush_target (&core_ops);
420 if (from_tty)
421 printf_filtered ("No core file now.\n");
422 }
423
424 /* Get the registers out of a core file. This is the machine-
425 independent part. Fetch_core_registers is the machine-dependent
426 part, typically implemented in the xm-file for each architecture. */
427
428 /* We just get all the registers, so we don't use regno. */
429 /* ARGSUSED */
430 static void
431 get_core_registers (regno)
432 int regno;
433 {
434 sec_ptr reg_sec;
435 unsigned size;
436 char *the_regs;
437 char regsecname[20];
438
439 sprintf (regsecname, ".reg%d", TIDGET (inferior_pid));
440
441 reg_sec = bfd_get_section_by_name (core_bfd, regsecname);
442 if (!reg_sec)
443 goto cant;
444 size = bfd_section_size (core_bfd, reg_sec);
445 the_regs = alloca (size);
446 if (bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0,
447 size))
448 {
449 fetch_core_registers (the_regs, size, 0,
450 (unsigned) bfd_section_vma (abfd,reg_sec));
451 }
452 else
453 {
454 cant:
455 fprintf_filtered (stderr, "Couldn't fetch registers from core file: %s\n",
456 bfd_errmsg (bfd_error));
457 }
458
459 registers_fetched();
460 }
461
462 static void
463 core_files_info (t)
464 struct target_ops *t;
465 {
466 print_section_info (t, core_bfd);
467 }
468 \f
469 /* If mourn is being called in all the right places, this could be say
470 `gdb internal error' (since generic_mourn calls mark_breakpoints_out). */
471
472 static int
473 ignore (addr, contents)
474 CORE_ADDR addr;
475 char *contents;
476 {
477 }
478
479 static struct target_ops
480 lynx_core_ops =
481 {
482 "core",
483 "Local core dump file",
484 "Use a core file as a target. Specify the filename of the core file.",
485 lynx_core_open,
486 lynx_core_close,
487 find_default_attach,
488 lynx_core_detach,
489 0,
490 0,
491 get_core_registers,
492 0,
493 0,
494 xfer_memory,
495 lynx_core_files_info,
496 ignore,
497 ignore,
498 0,
499 0,
500 0,
501 0,
502 0,
503 0,
504 0,
505 0,
506 find_default_create_inferior,
507 0, /* mourn_inferior */
508 0, /* can_run */
509 0, /* notice_signals */
510 core_stratum,
511 0, /* next */
512 0,
513 1,
514 1,
515 1,
516 0,
517 0,
518 0,
519 OPS_MAGIC, /* Always the last thing */
520 };
521
522 void
523 _initialize_i386lynx_nat()
524 {
525 add_target (&lynx_core_ops);
526 }
527 #endif
This page took 0.040674 seconds and 5 git commands to generate.