386BSD 0.1 development
[unix-history] / usr / src / usr.bin / gdb / core.c
CommitLineData
cc61838f
WJ
1/*-
2 * This code is derived from software copyrighted by the Free Software
3 * Foundation.
4 *
5 * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
6 * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
7 */
8
9#ifndef lint
10static char sccsid[] = "@(#)core.c 6.3 (Berkeley) 5/8/91";
11#endif /* not lint */
12
13/* Work with core dump and executable files, for GDB.
14 Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
15
16This file is part of GDB.
17
18GDB is free software; you can redistribute it and/or modify
19it under the terms of the GNU General Public License as published by
20the Free Software Foundation; either version 1, or (at your option)
21any later version.
22
23GDB is distributed in the hope that it will be useful,
24but WITHOUT ANY WARRANTY; without even the implied warranty of
25MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26GNU General Public License for more details.
27
28You should have received a copy of the GNU General Public License
29along with GDB; see the file COPYING. If not, write to
30the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
31
32#include <stdio.h>
33#include "defs.h"
34#include "param.h"
35#include "frame.h" /* required by inferior.h */
36#include "inferior.h"
37
38#ifdef USG
39#include <sys/types.h>
40#include <fcntl.h>
41#endif
42
43#ifdef COFF_ENCAPSULATE
44#include "a.out.encap.h"
45#else
46#include <a.out.h>
47#endif
48#ifndef N_MAGIC
49#ifdef COFF_FORMAT
50#define N_MAGIC(exec) ((exec).magic)
51#else
52#define N_MAGIC(exec) ((exec).a_magic)
53#endif
54#endif
55#include <signal.h>
56#include <sys/param.h>
57#include <sys/dir.h>
58#include <sys/file.h>
59#include <sys/stat.h>
60
61#ifdef UMAX_CORE
62#include <sys/ptrace.h>
63#else
64#include <sys/user.h>
65#endif
66
67#ifndef N_TXTADDR
68#define N_TXTADDR(hdr) 0
69#endif /* no N_TXTADDR */
70
71#ifndef N_DATADDR
72#define N_DATADDR(hdr) hdr.a_text
73#endif /* no N_DATADDR */
74
75#ifndef COFF_FORMAT
76#ifndef AOUTHDR
77#define AOUTHDR struct exec
78#endif
79#endif
80
81extern char *sys_siglist[];
82
83extern core_file_command (), exec_file_command ();
84
85/* Hook for `exec_file_command' command to call. */
86
87void (*exec_file_display_hook) ();
88
89/* File names of core file and executable file. */
90
91char *corefile;
92char *execfile;
93
94/* Descriptors on which core file and executable file are open.
95 Note that the execchan is closed when an inferior is created
96 and reopened if the inferior dies or is killed. */
97
98int corechan;
99int execchan;
100
101/* Last modification time of executable file.
102 Also used in source.c to compare against mtime of a source file. */
103
104int exec_mtime;
105
106/* Virtual addresses of bounds of the two areas of memory in the core file. */
107
108CORE_ADDR data_start;
109CORE_ADDR data_end;
110CORE_ADDR stack_start;
111CORE_ADDR stack_end;
112
113#if defined (REG_STACK_SEGMENT)
114/* Start and end of the register stack segment. */
115CORE_ADDR reg_stack_start;
116CORE_ADDR reg_stack_end;
117#endif /* REG_STACK_SEGMENT */
118
119/* Virtual addresses of bounds of two areas of memory in the exec file.
120 Note that the data area in the exec file is used only when there is no core file. */
121
122CORE_ADDR text_start;
123CORE_ADDR text_end;
124
125CORE_ADDR exec_data_start;
126CORE_ADDR exec_data_end;
127
128/* Offset within executable file of start of text area data. */
129
130int text_offset;
131
132/* Offset within executable file of start of data area data. */
133
134int exec_data_offset;
135
136/* Offset within core file of start of data area data. */
137
138int data_offset;
139
140/* Offset within core file of start of stack area data. */
141
142int stack_offset;
143
144#ifdef COFF_FORMAT
145/* various coff data structures */
146
147FILHDR file_hdr;
148SCNHDR text_hdr;
149SCNHDR data_hdr;
150
151#endif /* not COFF_FORMAT */
152
153/* a.out header saved in core file. */
154
155AOUTHDR core_aouthdr;
156
157/* a.out header of exec file. */
158
159AOUTHDR exec_aouthdr;
160
161void validate_files ();
162unsigned int register_addr ();
163\f
164/* Call this to specify the hook for exec_file_command to call back.
165 This is called from the x-window display code. */
166
167void
168specify_exec_file_hook (hook)
169 void (*hook) ();
170{
171 exec_file_display_hook = hook;
172}
173
174/* The exec file must be closed before running an inferior.
175 If it is needed again after the inferior dies, it must
176 be reopened. */
177
178void
179close_exec_file ()
180{
181 if (execchan >= 0)
182 close (execchan);
183 execchan = -1;
184}
185
186void
187reopen_exec_file ()
188{
189 if (execchan < 0 && execfile != 0)
190 {
191 char *filename = concat (execfile, "", "");
192 exec_file_command (filename, 0);
193 free (filename);
194 }
195}
196\f
197/* If we have both a core file and an exec file,
198 print a warning if they don't go together.
199 This should really check that the core file came
200 from that exec file, but I don't know how to do it. */
201
202void
203validate_files ()
204{
205 if (execfile != 0 && corefile != 0)
206 {
207 struct stat st_core;
208
209 if (fstat (corechan, &st_core) < 0)
210 /* It might be a good idea to print an error message.
211 On the other hand, if the user tries to *do* anything with
212 the core file, (s)he'll find out soon enough. */
213 return;
214
215 if (N_MAGIC (core_aouthdr) != 0
216 && bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr))
217 printf ("Warning: core file does not match specified executable file.\n");
218 else if (exec_mtime > st_core.st_mtime) {
219#ifdef KERNELDEBUG
220 extern int kernel_debugging;
221 if (!kernel_debugging)
222#endif
223 printf ("Warning: exec file is newer than core file.\n");
224 }
225 }
226}
227
228/* Return the name of the executable file as a string.
229 ERR nonzero means get error if there is none specified;
230 otherwise return 0 in that case. */
231
232char *
233get_exec_file (err)
234 int err;
235{
236 if (err && execfile == 0)
237 error ("No executable file specified.\n\
238Use the \"exec-file\" and \"symbol-file\" commands.");
239 return execfile;
240}
241
242int
243have_core_file_p ()
244{
245 return corefile != 0;
246}
247
248static void
249files_info ()
250{
251 char *symfile;
252 extern char *get_sym_file ();
253
254 if (execfile)
255 printf ("Executable file \"%s\".\n", execfile);
256 else
257 printf ("No executable file\n");
258 if (corefile == 0)
259 printf ("No core dump file\n");
260 else
261 printf ("Core dump file \"%s\".\n", corefile);
262
263 if (have_inferior_p ())
264 printf ("Using the running image of the program, rather than these files.\n");
265
266 symfile = get_sym_file ();
267 if (symfile != 0)
268 printf ("Symbols from \"%s\".\n", symfile);
269
270#ifdef FILES_INFO_HOOK
271 if (FILES_INFO_HOOK ())
272 return;
273#endif
274
275 if (! have_inferior_p ())
276 {
277 if (execfile)
278 {
279 printf ("Text segment in executable from 0x%x to 0x%x.\n",
280 text_start, text_end);
281 printf ("Data segment in executable from 0x%x to 0x%x.\n",
282 exec_data_start, exec_data_end);
283 if (corefile)
284 printf ("(But since we have a core file, we're using...)\n");
285 }
286 if (corefile)
287 {
288 printf ("Data segment in core file from 0x%x to 0x%x.\n",
289 data_start, data_end);
290 printf ("Stack segment in core file from 0x%x to 0x%x.\n",
291 stack_start, stack_end);
292 }
293 }
294}
295\f
296/* Read "memory data" from core file and/or executable file.
297 Returns zero if successful, 1 if xfer_core_file failed, errno value if
298 ptrace failed. */
299
300int
301read_memory (memaddr, myaddr, len)
302 CORE_ADDR memaddr;
303 char *myaddr;
304 int len;
305{
306 if (len == 0)
307 return 0;
308
309 if (have_inferior_p ())
310 {
311 if (remote_debugging)
312 return remote_read_inferior_memory (memaddr, myaddr, len);
313 else
314 return read_inferior_memory (memaddr, myaddr, len);
315 }
316 else
317 return xfer_core_file (memaddr, myaddr, len);
318}
319
320/* Write LEN bytes of data starting at address MYADDR
321 into debugged program memory at address MEMADDR.
322 Returns zero if successful, or an errno value if ptrace failed. */
323
324int
325write_memory (memaddr, myaddr, len)
326 CORE_ADDR memaddr;
327 char *myaddr;
328 int len;
329{
330 if (have_inferior_p ())
331 {
332 if (remote_debugging)
333 return remote_write_inferior_memory (memaddr, myaddr, len);
334 else
335 return write_inferior_memory (memaddr, myaddr, len);
336 }
337 else
338 error ("Can write memory only when program being debugged is running.");
339}
340
341#ifndef XFER_CORE_FILE
342int (*core_file_hook)(); /* hook to handle special core files like
343 like /dev/mem and crash dumps */
344
345/* Read from the program's memory (except for inferior processes).
346 This function is misnamed, since it only reads, never writes; and
347 since it will use the core file and/or executable file as necessary.
348
349 It should be extended to write as well as read, FIXME, for patching files.
350
351 Return 0 if address could be read, 1 if not. */
352
353int
354xfer_core_file (memaddr, myaddr, len)
355 CORE_ADDR memaddr;
356 char *myaddr;
357 int len;
358{
359 register int i;
360 register int val;
361 int xferchan;
362 char **xferfile;
363 int fileptr;
364 int returnval = 0;
365
366 if (core_file_hook)
367 return ((*core_file_hook)(memaddr, myaddr, len));
368
369 while (len > 0)
370 {
371 xferfile = 0;
372 xferchan = 0;
373
374 /* Determine which file the next bunch of addresses reside in,
375 and where in the file. Set the file's read/write pointer
376 to point at the proper place for the desired address
377 and set xferfile and xferchan for the correct file.
378
379 If desired address is nonexistent, leave them zero.
380
381 i is set to the number of bytes that can be handled
382 along with the next address.
383
384 We put the most likely tests first for efficiency. */
385
386 /* Note that if there is no core file
387 data_start and data_end are equal. */
388 if (memaddr >= data_start && memaddr < data_end)
389 {
390 i = min (len, data_end - memaddr);
391 fileptr = memaddr - data_start + data_offset;
392 xferfile = &corefile;
393 xferchan = corechan;
394 }
395 /* Note that if there is no core file
396 stack_start and stack_end are equal. */
397 else if (memaddr >= stack_start && memaddr < stack_end)
398 {
399 i = min (len, stack_end - memaddr);
400 fileptr = memaddr - stack_start + stack_offset;
401 xferfile = &corefile;
402 xferchan = corechan;
403 }
404#ifdef REG_STACK_SEGMENT
405 /* Pyramids have an extra segment in the virtual address space
406 for the (control) stack of register-window frames */
407 else if (memaddr >= reg_stack_start && memaddr < reg_stack_end)
408 {
409 i = min (len, reg_stack_end - memaddr);
410 fileptr = memaddr - reg_stack_start + reg_stack_offset;
411 xferfile = &corefile;
412 xferchan = corechan;
413 }
414#endif /* REG_STACK_SEGMENT */
415
416 else if (corechan < 0
417 && memaddr >= exec_data_start && memaddr < exec_data_end)
418 {
419 i = min (len, exec_data_end - memaddr);
420 fileptr = memaddr - exec_data_start + exec_data_offset;
421 xferfile = &execfile;
422 xferchan = execchan;
423 }
424 else if (memaddr >= text_start && memaddr < text_end)
425 {
426 i = min (len, text_end - memaddr);
427 fileptr = memaddr - text_start + text_offset;
428 xferfile = &execfile;
429 xferchan = execchan;
430 }
431 else if (memaddr < text_start)
432 {
433 i = min (len, text_start - memaddr);
434 }
435 else if (memaddr >= text_end
436 && memaddr < (corechan >= 0? data_start : exec_data_start))
437 {
438 i = min (len, data_start - memaddr);
439 }
440 else if (corechan >= 0
441 && memaddr >= data_end && memaddr < stack_start)
442 {
443 i = min (len, stack_start - memaddr);
444 }
445 else if (corechan < 0 && memaddr >= exec_data_end)
446 {
447 /* Since there is nothing at higher addresses than data
448 (without a core file or an inferior, there is no
449 stack, set i to do the rest of the operation now. */
450 i = len;
451 }
452#ifdef REG_STACK_SEGMENT
453 else if (memaddr >= reg_stack_end && reg_stack_end != 0)
454 {
455 i = min (len, reg_stack_start - memaddr);
456 }
457 else if (memaddr >= stack_end && memaddr < reg_stack_start)
458#else /* no REG_STACK_SEGMENT. */
459 else if (memaddr >= stack_end && stack_end != 0)
460#endif /* no REG_STACK_SEGMENT. */
461 {
462 /* Since there is nothing at higher addresses than
463 the stack, set i to do the rest of the operation now. */
464 i = len;
465 }
466 else
467 {
468 /* Address did not classify into one of the known ranges.
469 This shouldn't happen; we catch the endpoints. */
470 fatal ("Internal: Bad case logic in xfer_core_file.");
471 }
472
473 /* Now we know which file to use.
474 Set up its pointer and transfer the data. */
475 if (xferfile)
476 {
477 if (*xferfile == 0)
478 if (xferfile == &execfile)
479 error ("No program file to examine.");
480 else
481 error ("No core dump file or running program to examine.");
482 val = lseek (xferchan, fileptr, 0);
483 if (val == -1)
484 perror_with_name (*xferfile);
485 val = myread (xferchan, myaddr, i);
486 if (val < 0)
487 perror_with_name (*xferfile);
488 }
489 /* If this address is for nonexistent memory,
490 read zeros if reading, or do nothing if writing.
491 Actually, we never right. */
492 else
493 {
494 bzero (myaddr, i);
495 returnval = 1;
496 }
497
498 memaddr += i;
499 myaddr += i;
500 len -= i;
501 }
502 return returnval;
503}
504#endif /* XFER_CORE_FILE */
505\f
506/* My replacement for the read system call.
507 Used like `read' but keeps going if `read' returns too soon. */
508
509int
510myread (desc, addr, len)
511 int desc;
512 char *addr;
513 int len;
514{
515 register int val;
516 int orglen = len;
517
518 while (len > 0)
519 {
520 val = read (desc, addr, len);
521 if (val < 0)
522 return val;
523 if (val == 0)
524 return orglen - len;
525 len -= val;
526 addr += val;
527 }
528 return orglen;
529}
530\f
531#ifdef REGISTER_U_ADDR
532
533/* Return the address in the core dump or inferior of register REGNO.
534 BLOCKEND is the address of the end of the user structure. */
535
536unsigned int
537register_addr (regno, blockend)
538 int regno;
539 int blockend;
540{
541 int addr;
542
543 if (regno < 0 || regno >= NUM_REGS)
544 error ("Invalid register number %d.", regno);
545
546 REGISTER_U_ADDR (addr, blockend, regno);
547
548 return addr;
549}
550
551#endif /* REGISTER_U_ADDR */
552\f
553void
554_initialize_core()
555{
556 corechan = -1;
557 execchan = -1;
558 corefile = 0;
559 execfile = 0;
560 exec_file_display_hook = 0;
561
562 text_start = 0;
563 text_end = 0;
564 data_start = 0;
565 data_end = 0;
566 exec_data_start = 0;
567 exec_data_end = 0;
568 stack_start = STACK_END_ADDR;
569 stack_end = STACK_END_ADDR;
570
571 add_com ("core-file", class_files, core_file_command,
572 "Use FILE as core dump for examining memory and registers.\n\
573No arg means have no core file.");
574 add_com ("exec-file", class_files, exec_file_command,
575 "Use FILE as program for getting contents of pure memory.\n\
576If FILE cannot be found as specified, your execution directory path\n\
577is searched for a command of that name.\n\
578No arg means have no executable file.");
579 add_info ("files", files_info, "Names of files being debugged.");
580}
581