aboutsummaryrefslogtreecommitdiff
path: root/gdb/core.c
diff options
context:
space:
mode:
authorgdb-3.1 <gdb@fsf.org>1989-01-31 17:56:40 +0000
committerPedro Alves <palves@redhat.com>2012-06-03 15:36:31 +0100
commite91b87a36830d061ef87d67be5f309e4d4ed918f (patch)
tree3408ea913a9cccd51c9b7d0b3bc7d7897cac8a5b /gdb/core.c
parentbb7592f01006b09c846831a9fb9c306307ba34f6 (diff)
downloadbinutils-e91b87a36830d061ef87d67be5f309e4d4ed918f.zip
binutils-e91b87a36830d061ef87d67be5f309e4d4ed918f.tar.gz
binutils-e91b87a36830d061ef87d67be5f309e4d4ed918f.tar.bz2
gdb-3.1
Diffstat (limited to 'gdb/core.c')
-rw-r--r--gdb/core.c530
1 files changed, 128 insertions, 402 deletions
diff --git a/gdb/core.c b/gdb/core.c
index 85a8d24..03f4a68 100644
--- a/gdb/core.c
+++ b/gdb/core.c
@@ -1,5 +1,5 @@
/* Work with core dump and executable files, for GDB.
- Copyright (C) 1986, 1987 Free Software Foundation, Inc.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY. No author or distributor accepts responsibility to anyone
@@ -18,11 +18,29 @@ In other words, go ahead and share GDB, but don't try to stop
anyone else from sharing it farther. Help stamp out software hoarding!
*/
-#include "initialize.h"
#include "defs.h"
#include "param.h"
+#include "gdbcore.h"
+#ifdef USG
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#else
#include <a.out.h>
+#endif
+
+#ifndef N_MAGIC
+#ifdef COFF_FORMAT
+#define N_MAGIC(exec) ((exec).magic)
+#else
+#define N_MAGIC(exec) ((exec).a_magic)
+#endif
+#endif
+
#include <stdio.h>
#include <signal.h>
#include <sys/param.h>
@@ -30,28 +48,21 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#include <sys/file.h>
#include <sys/stat.h>
-/* Recognize COFF format systems because a.out.h defines AOUTHDR. */
-#ifdef AOUTHDR
-#define COFF_FORMAT
+#ifdef UNISOFT_ASSHOLES
+#define PMMU
+#define NEW_PMMU
+#include <sys/seg.h> /* Required for user.ps */
+#include <sys/time.h> /* '' */
+#include <sys/mmu.h> /* '' */
+#include <sys/reg.h>
+#define mc68881 /* Required to get float in user.ps */
#endif
-#ifdef NEW_SUN_CORE
-#include <sys/core.h>
-#else /* not NEW_SUN_CORE */
#ifdef UMAX_CORE
#include <sys/ptrace.h>
-#else /* not UMAX_CORE */
+#else
#include <sys/user.h>
-#ifdef HP9K320
-#include <sys/reg.h>
-#include <sys/trap.h>
-#ifdef HPUX_VERSION_5
-#define e_PS e_regs[PS]
-#define e_PC e_regs[PC]
-#endif /* HPUX_VERSION_5 */
-#endif /* HP9K320 */
-#endif /* not UMAX_CORE */
-#endif /* not NEW_SUN_CORE */
+#endif
#ifndef N_TXTADDR
#define N_TXTADDR(hdr) 0
@@ -61,20 +72,13 @@ anyone else from sharing it farther. Help stamp out software hoarding!
#define N_DATADDR(hdr) hdr.a_text
#endif /* no N_DATADDR */
-/* Make COFF and non-COFF names for things a little more compatible
- to reduce conditionals later. */
-
-#ifdef COFF_FORMAT
-#define a_magic magic
-#endif
-
#ifndef COFF_FORMAT
-#define AOUTHDR struct exec
+#define AOUTHDR struct exec
#endif
extern char *sys_siglist[];
-START_FILE
+extern core_file_command (), exec_file_command ();
/* Hook for `exec_file_command' command to call. */
@@ -82,15 +86,15 @@ void (*exec_file_display_hook) ();
/* File names of core file and executable file. */
-static char *corefile;
-static char *execfile;
+char *corefile;
+char *execfile;
/* Descriptors on which core file and executable file are open.
Note that the execchan is closed when an inferior is created
and reopened if the inferior dies or is killed. */
-static int corechan;
-static int execchan;
+int corechan;
+int execchan;
/* Last modification time of executable file.
Also used in source.c to compare against mtime of a source file. */
@@ -99,10 +103,10 @@ int exec_mtime;
/* Virtual addresses of bounds of the two areas of memory in the core file. */
-static CORE_ADDR data_start;
-static CORE_ADDR data_end;
-static CORE_ADDR stack_start;
-static CORE_ADDR stack_end;
+CORE_ADDR data_start;
+CORE_ADDR data_end;
+CORE_ADDR stack_start;
+CORE_ADDR stack_end;
/* Virtual addresses of bounds of two areas of memory in the exec file.
Note that the data area in the exec file is used only when there is no core file. */
@@ -110,361 +114,49 @@ static CORE_ADDR stack_end;
CORE_ADDR text_start;
CORE_ADDR text_end;
-static CORE_ADDR exec_data_start;
-static CORE_ADDR exec_data_end;
+CORE_ADDR exec_data_start;
+CORE_ADDR exec_data_end;
/* Address in executable file of start of text area data. */
-static int text_offset;
+int text_offset;
/* Address in executable file of start of data area data. */
-static int exec_data_offset;
+int exec_data_offset;
/* Address in core file of start of data area data. */
-static int data_offset;
+int data_offset;
/* Address in core file of start of stack area data. */
-static int stack_offset;
+int stack_offset;
#ifdef COFF_FORMAT
/* various coff data structures */
-static FILHDR file_hdr;
-static SCNHDR text_hdr;
-static SCNHDR data_hdr;
+FILHDR file_hdr;
+SCNHDR text_hdr;
+SCNHDR data_hdr;
#endif /* not COFF_FORMAT */
/* a.out header saved in core file. */
-static AOUTHDR core_aouthdr;
+AOUTHDR core_aouthdr;
/* a.out header of exec file. */
-static AOUTHDR exec_aouthdr;
+AOUTHDR exec_aouthdr;
-static void validate_files ();
+void validate_files ();
unsigned int register_addr ();
-core_file_command (filename, from_tty)
- char *filename;
- int from_tty;
-{
- int val;
- extern char registers[];
-
- /* Discard all vestiges of any previous core file
- and mark data and stack spaces as empty. */
-
- if (corefile)
- free (corefile);
- corefile = 0;
-
- if (corechan >= 0)
- close (corechan);
- corechan = -1;
-
- data_start = 0;
- data_end = 0;
- stack_start = STACK_END_ADDR;
- stack_end = STACK_END_ADDR;
-
- /* Now, if a new core file was specified, open it and digest it. */
-
- if (filename)
- {
- if (have_inferior_p ())
- error ("To look at a core file, you must kill the inferior with \"kill\".");
- corechan = open (filename, O_RDONLY, 0);
- if (corechan < 0)
- perror_with_name (filename);
-#ifdef NEW_SUN_CORE
- {
- struct core corestr;
-
- val = myread (corechan, &corestr, sizeof corestr);
- if (val < 0)
- perror_with_name (filename);
- if (corestr.c_magic != CORE_MAGIC)
- error ("\"%s\" does not appear to be a core dump file (magic 0x%x, expected 0x%x)",
- filename, corestr.c_magic, (int) CORE_MAGIC);
- else if (sizeof (struct core) != corestr.c_len)
- error ("\"%s\" has an invalid struct core length (%d, expected %d)",
- filename, corestr.c_len, (int) sizeof (struct core));
-
- data_start = exec_data_start;
- data_end = data_start + corestr.c_dsize;
- stack_start = stack_end - corestr.c_ssize;
- data_offset = sizeof corestr;
- stack_offset = sizeof corestr + corestr.c_dsize;
-
-#if defined(sun2) || defined(sun3)
- bcopy (&corestr.c_regs, registers, 16 * 4);
- *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
- *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
- bcopy (corestr.c_fpstatus.fps_regs,
- &registers[REGISTER_BYTE (FP0_REGNUM)],
- sizeof corestr.c_fpstatus.fps_regs);
- bcopy (&corestr.c_fpstatus.fps_control,
- &registers[REGISTER_BYTE (FPC_REGNUM)],
- sizeof corestr.c_fpstatus - sizeof corestr.c_fpstatus.fps_regs);
-#endif
-#if defined(sun4)
- /* G0 *always* holds 0. */
- *(int *)&registers[REGISTER_BYTE (0)] = 0;
- /* The globals and output registers. I don't know where
- to get the locals and input registers from the core file. */
- bcopy (&corestr.c_regs.r_g1, registers, 15 * 4);
- *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = corestr.c_regs.r_ps;
- *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = corestr.c_regs.r_pc;
- *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = corestr.c_regs.r_npc;
- *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = corestr.c_regs.r_y;
- bcopy (corestr.c_fpu.fpu_regs,
- &registers[REGISTER_BYTE (FP0_REGNUM)],
- sizeof corestr.c_fpu.fpu_regs);
-#ifdef FPU
- bcopy (&corestr.c_fpu.fpu_fsr,
- &registers[REGISTER_BYTE (FPS_REGNUM)],
- sizeof (FPU_FSR_TYPE));
-#endif
-#endif
-
- bcopy (&corestr.c_aouthdr, &core_aouthdr, sizeof (struct exec));
-
- printf ("Core file is from \"%s\".\n", corestr.c_cmdname);
- if (corestr.c_signo > 0)
- printf ("Program terminated with signal %d, %s.\n",
- corestr.c_signo,
- corestr.c_signo < NSIG
- ? sys_siglist[corestr.c_signo]
- : "(undocumented)");
- }
-#else /* not NEW_SUN_CORE */
- /* 4.2-style (and perhaps also sysV-style) core dump file. */
- {
-#ifdef UMAX_CORE
- struct ptrace_user u;
-#else
- struct user u;
-#endif
- int reg_offset;
-
- val = myread (corechan, &u, sizeof u);
- if (val < 0)
- perror_with_name (filename);
- data_start = exec_data_start;
-
-#ifdef UMAX_CORE
- data_end = data_start + u.pt_dsize;
- stack_start = stack_end - u.pt_ssize;
- data_offset = sizeof u;
- stack_offset = data_offset + u.pt_dsize;
- reg_offset = 0;
-
- bcopy (&u.pt_aouthdr, &core_aouthdr, sizeof (AOUTHDR));
- printf ("Core file is from \"%s\".\n", u.pt_comm);
- if (u.pt_signal > 0)
- printf ("Program terminated with signal %d, %s.\n",
- u.pt_signal,
- u.pt_signal < NSIG
- ? sys_siglist[u.pt_signal]
- : "(undocumented)");
-#else /* not UMAX_CORE */
- data_end = data_start + NBPG * u.u_dsize;
- stack_start = stack_end - NBPG * u.u_ssize;
- data_offset = NBPG * UPAGES;
- stack_offset = NBPG * (UPAGES + u.u_dsize);
- reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
-
- /* I don't know where to find this info.
- So, for now, mark it as not available. */
- core_aouthdr.a_magic = 0;
-#endif /* not UMAX_CORE */
-
- /* Read the register values out of the core file and store
- them where `read_register' will find them. */
-
-#ifdef HP9K320
- {
- register int regno;
- struct exception_stack es;
- int val;
-
- val = lseek (corechan, (REGISTER_ADDR (reg_offset, 0)), 0);
- if (val < 0)
- perror_with_name (filename);
- val = myread (corechan, es,
- ((char *) &es.e_regs[R0] - (char *) &es.e_offset));
- if (val < 0)
- perror_with_name (filename);
- for (regno = 0; (regno < PS_REGNUM); regno++)
- supply_register (regno, &es.e_regs[regno + R0]);
- val = es.e_PS;
- supply_register (regno++, &val);
- supply_register (regno++, &es.e_PC);
- for (; (regno < NUM_REGS); regno++)
- {
- char buf[MAX_REGISTER_RAW_SIZE];
-
- val = lseek (corechan, (FP_REGISTER_ADDR (u, regno)), 0);
- if (val < 0)
- perror_with_name (filename);
-
- val = myread (corechan, buf, sizeof buf);
- if (val < 0)
- perror_with_name (filename);
- supply_register (regno, buf);
- }
- }
-#else /* not HP9K320 */
- {
- register int regno;
-
- for (regno = 0; regno < NUM_REGS; regno++)
- {
- char buf[MAX_REGISTER_RAW_SIZE];
-
- val = lseek (corechan, register_addr (regno, reg_offset), 0);
- if (val < 0)
- perror_with_name (filename);
-
- val = myread (corechan, buf, sizeof buf);
- if (val < 0)
- perror_with_name (filename);
- supply_register (regno, buf);
- }
- }
-#endif /* not HP9K320 */
- }
-#endif /* not NEW_SUN_CORE */
- if (filename[0] == '/')
- corefile = savestring (filename, strlen (filename));
- else
- {
- corefile = concat (current_directory, "/", filename);
- }
-
- set_current_frame (read_register (FP_REGNUM));
- select_frame (get_current_frame (), 0);
- validate_files ();
- }
- else if (from_tty)
- printf ("No core file now.\n");
-}
-
-exec_file_command (filename, from_tty)
- char *filename;
- int from_tty;
-{
- int val;
-
- /* Eliminate all traces of old exec file.
- Mark text segment as empty. */
-
- if (execfile)
- free (execfile);
- execfile = 0;
- data_start = 0;
- data_end -= exec_data_start;
- text_start = 0;
- text_end = 0;
- exec_data_start = 0;
- exec_data_end = 0;
- if (execchan >= 0)
- close (execchan);
- execchan = -1;
-
- /* Now open and digest the file the user requested, if any. */
-
- if (filename)
- {
- execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
- &execfile);
- if (execchan < 0)
- perror_with_name (filename);
-
-#ifdef COFF_FORMAT
- {
- int aout_hdrsize;
- int num_sections;
-
- if (read_file_hdr (execchan, &file_hdr) < 0)
- error ("\"%s\": not in executable format.", execfile);
-
- aout_hdrsize = file_hdr.f_opthdr;
- num_sections = file_hdr.f_nscns;
-
- if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
- error ("\"%s\": can't read optional aouthdr", execfile);
-
- if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections) < 0)
- error ("\"%s\": can't read text section header", execfile);
-
- if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections) < 0)
- error ("\"%s\": can't read data section header", execfile);
-
- text_start = exec_aouthdr.text_start;
- text_end = text_start + exec_aouthdr.tsize;
- text_offset = text_hdr.s_scnptr;
- exec_data_start = exec_aouthdr.data_start;
- exec_data_end = exec_data_start + exec_aouthdr.dsize;
- exec_data_offset = data_hdr.s_scnptr;
- data_start = exec_data_start;
- data_end += exec_data_start;
- exec_mtime = file_hdr.f_timdat;
- }
-#else /* not COFF_FORMAT */
- {
- struct stat st_exec;
-
-#ifdef gould
- FILHDR exec_coffhdr;
-
- val = myread (execchan, &exec_coffhdr, sizeof exec_coffhdr);
- if (val < 0)
- perror_with_name (filename);
-#endif
- val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
-
- if (val < 0)
- perror_with_name (filename);
-
- text_start = N_TXTADDR (exec_aouthdr);
- exec_data_start = N_DATADDR (exec_aouthdr);
-#ifdef gould
- text_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr);
- exec_data_offset = N_TXTOFF (exec_coffhdr, exec_aouthdr)
- + exec_aouthdr.a_text;
-#else
- text_offset = N_TXTOFF (exec_aouthdr);
- exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
-#endif
- text_end = text_start + exec_aouthdr.a_text;
- exec_data_end = exec_data_start + exec_aouthdr.a_data;
- data_start = exec_data_start;
- data_end += exec_data_start;
-
- fstat (execchan, &st_exec);
- exec_mtime = st_exec.st_mtime;
- }
-#endif /* not COFF_FORMAT */
-
- validate_files ();
- }
- else if (from_tty)
- printf ("No exec file now.\n");
-
- /* Tell display code (if any) about the changed file name. */
- if (exec_file_display_hook)
- (*exec_file_display_hook) (filename);
-}
-
/* Call this to specify the hook for exec_file_command to call back.
This is called from the x-window display code. */
+void
specify_exec_file_hook (hook)
void (*hook) ();
{
@@ -475,6 +167,7 @@ specify_exec_file_hook (hook)
If it is needed again after the inferior dies, it must
be reopened. */
+void
close_exec_file ()
{
if (execchan >= 0)
@@ -482,6 +175,7 @@ close_exec_file ()
execchan = -1;
}
+void
reopen_exec_file ()
{
if (execchan < 0 && execfile != 0)
@@ -497,7 +191,7 @@ reopen_exec_file ()
This should really check that the core file came
from that exec file, but I don't know how to do it. */
-static void
+void
validate_files ()
{
if (execfile != 0 && corefile != 0)
@@ -506,7 +200,7 @@ validate_files ()
fstat (corechan, &st_core);
- if (core_aouthdr.a_magic != 0
+ if (N_MAGIC (core_aouthdr) != 0
&& bcmp (&core_aouthdr, &exec_aouthdr, sizeof core_aouthdr))
printf ("Warning: core file does not match specified executable file.\n");
else if (exec_mtime > st_core.st_mtime)
@@ -544,49 +238,54 @@ files_info ()
printf ("Executable file \"%s\".\n", execfile);
else
printf ("No executable file\n");
- if (corefile == 0)
- printf ("No core dump file\n");
+
+ if (corefile)
+ printf ("Core dump file \"%s\".\n", corefile);
else
- printf ("Core dump file \"%s\".\n", corefile);
+ printf ("No core dump file\n");
if (have_inferior_p ())
printf ("Using the running image of the program, rather than these files.\n");
symfile = get_sym_file ();
if (symfile != 0)
- printf ("Symbols loaded from \"%s\".\n", symfile);
+ printf ("Symbols from \"%s\".\n", symfile);
if (! have_inferior_p ())
{
if (execfile)
{
- printf ("Text segment from 0x%x to 0x%x.\n",
+ printf ("Text segment in executable from 0x%x to 0x%x.\n",
text_start, text_end);
+ printf ("Data segment in executable from 0x%x to 0x%x.\n",
+ exec_data_start, exec_data_end);
+ if (corefile)
+ printf("(But since we have a core file, we're using...)\n");
}
if (corefile)
{
- printf ("Data segment from 0x%x to 0x%x.\nStack segment from 0x%x to 0x%x.\n",
- data_start, data_end, stack_start, stack_end);
- }
- else
- {
- printf ("Data segment in executable from 0x%x to 0x%x.\n",
- exec_data_start, exec_data_end);
+ printf ("Data segment in core file from 0x%x to 0x%x.\n",
+ data_start, data_end);
+ printf ("Stack segment in core file from 0x%x to 0x%x.\n",
+ stack_start, stack_end);
}
}
}
-/* Read "memory data" from core file and/or executable file */
+/* Read "memory data" from core file and/or executable file.
+ Returns zero if successful, 1 if xfer_core_file failed, errno value if
+ ptrace failed. */
+int
read_memory (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
if (have_inferior_p ())
- read_inferior_memory (memaddr, myaddr, len);
+ return read_inferior_memory (memaddr, myaddr, len);
else
- xfer_core_file (memaddr, myaddr, len, 0);
+ return xfer_core_file (memaddr, myaddr, len);
}
/* Write LEN bytes of data starting at address MYADDR
@@ -605,6 +304,15 @@ write_memory (memaddr, myaddr, len)
error ("Can write memory only when program being debugged is running.");
}
+/* Read from the program's memory (except for inferior processes).
+ This function is misnamed, since it only reads, never writes; and
+ since it will use the core file and/or executable file as necessary.
+
+ It should be extended to write as well as read, FIXME, for patching files.
+
+ Return 0 if address could be read, 1 if not. */
+
+int
xfer_core_file (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
@@ -615,6 +323,7 @@ xfer_core_file (memaddr, myaddr, len)
int xferchan;
char **xferfile;
int fileptr;
+ int returnval = 0;
while (len > 0)
{
@@ -625,30 +334,17 @@ xfer_core_file (memaddr, myaddr, len)
and where in the file. Set the file's read/write pointer
to point at the proper place for the desired address
and set xferfile and xferchan for the correct file.
+
If desired address is nonexistent, leave them zero.
+
i is set to the number of bytes that can be handled
- along with the next address. */
+ along with the next address.
+
+ We put the most likely tests first for efficiency. */
- if (memaddr < text_start)
- {
- i = min (len, text_start - memaddr);
- }
- else if (memaddr >= text_end && memaddr < data_start)
- {
- i = min (len, data_start - memaddr);
- }
- else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end)
- && memaddr < stack_start)
- {
- i = min (len, stack_start - memaddr);
- }
- else if (memaddr >= stack_end && stack_end != 0)
- {
- i = min (len, - memaddr);
- }
/* Note that if there is no core file
data_start and data_end are equal. */
- else if (memaddr >= data_start && memaddr < data_end)
+ if (memaddr >= data_start && memaddr < data_end)
{
i = min (len, data_end - memaddr);
fileptr = memaddr - data_start + data_offset;
@@ -679,6 +375,31 @@ xfer_core_file (memaddr, myaddr, len)
xferfile = &execfile;
xferchan = execchan;
}
+ else if (memaddr < text_start)
+ {
+ i = min (len, text_start - memaddr);
+ }
+ else if (memaddr >= text_end
+ && memaddr < (corechan >= 0? data_start : exec_data_start))
+ {
+ i = min (len, data_start - memaddr);
+ }
+ else if (memaddr >= (corechan >= 0 ? data_end : exec_data_end)
+ && memaddr < stack_start)
+ {
+ i = min (len, stack_start - memaddr);
+ }
+ else if (memaddr >= stack_end && stack_end != 0)
+ {
+ i = min (len, - memaddr);
+ }
+ else
+ {
+ /* Address did not classify into one of the known ranges.
+ This could be because data_start != exec_data_start
+ or data_end similarly. */
+ abort();
+ }
/* Now we know which file to use.
Set up its pointer and transfer the data. */
@@ -697,19 +418,25 @@ xfer_core_file (memaddr, myaddr, len)
perror_with_name (*xferfile);
}
/* If this address is for nonexistent memory,
- read zeros if reading, or do nothing if writing. */
+ read zeros if reading, or do nothing if writing.
+ (FIXME we never write.) */
else
- bzero (myaddr, i);
+ {
+ bzero (myaddr, i);
+ returnval = 1;
+ }
memaddr += i;
myaddr += i;
len -= i;
}
+ return returnval;
}
/* My replacement for the read system call.
Used like `read' but keeps going if `read' returns too soon. */
+int
myread (desc, addr, len)
int desc;
char *addr;
@@ -753,8 +480,8 @@ register_addr (regno, blockend)
#endif /* REGISTER_U_ADDR */
-static
-initialize ()
+void
+_initialize_core()
{
corechan = -1;
execchan = -1;
@@ -782,4 +509,3 @@ No arg means have no executable file.");
add_info ("files", files_info, "Names of files being debugged.");
}
-END_FILE