1992-02-22 09:46:16 +08:00
|
|
|
|
/* Support for dumping and reloading various pieces of GDB's internal state.
|
|
|
|
|
Copyright 1992 Free Software Foundation, Inc.
|
|
|
|
|
Contributed by Cygnus Support, using pieces from other GDB modules.
|
|
|
|
|
|
|
|
|
|
This file is part of GDB.
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
|
|
|
|
|
|
|
/* This file provides support for dumping and then later reloading various
|
|
|
|
|
portions of gdb's internal state. It was originally implemented to
|
|
|
|
|
support a need for mapping in an image of gdb's symbol table from an
|
|
|
|
|
external file, where this image was created by an external program, such
|
|
|
|
|
as an incremental linker. However, it was generalized to enable future
|
|
|
|
|
support for dumping and reloading various other useful pieces of gdb's
|
|
|
|
|
internal state.
|
|
|
|
|
|
|
|
|
|
State files have a fairly simple form which is intended to be easily
|
|
|
|
|
extensible. The basic format is:
|
|
|
|
|
|
|
|
|
|
<file-header> <state-data> <form-tree>
|
|
|
|
|
|
|
|
|
|
Where:
|
|
|
|
|
|
|
|
|
|
file-header A simple file-header containing a magic number
|
|
|
|
|
so that gdb (and other readers) can quickly
|
|
|
|
|
determine what kind of file this is, and a file
|
|
|
|
|
offset to the root of the form-tree.
|
|
|
|
|
|
|
|
|
|
state-data The "raw" state-data that is referenced by nodes
|
|
|
|
|
in the form-tree.
|
|
|
|
|
|
|
|
|
|
form-tree A tree of arbitrarily sized nodes containing
|
|
|
|
|
information about gdb's internal state, and
|
|
|
|
|
possibly referencing data in the state-data section
|
|
|
|
|
of the file. Resembles DWARF in some respects.
|
|
|
|
|
|
|
|
|
|
When writing a state file, a hole is left for the file-header at the
|
|
|
|
|
beginning of the file, the state data is written immediately after the
|
|
|
|
|
file header (while storing the file offsets and sizes back into the
|
|
|
|
|
internal form-tree along the way), the form-tree itself is written
|
|
|
|
|
at the end of the file, and then the file header is written by seeking
|
|
|
|
|
back to the beginning of the file. This order is required because
|
|
|
|
|
the form tree contains file offsets and sizes in the state data portion
|
|
|
|
|
of the file, and the file header contains the file offset to the start
|
|
|
|
|
of the form tree.
|
|
|
|
|
|
|
|
|
|
Readers simply open the file, validate the magic number, seek to the
|
|
|
|
|
root of the form-tree, and walk the tree looking for the information that
|
|
|
|
|
they are interested in (and ignoring things that they aren't, or don't
|
|
|
|
|
understand).
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "defs.h"
|
|
|
|
|
#include "symtab.h"
|
|
|
|
|
#include "bfd.h"
|
|
|
|
|
#include "symfile.h"
|
|
|
|
|
#include "state.h"
|
|
|
|
|
|
|
|
|
|
#ifndef SEEK_SET
|
|
|
|
|
#define SEEK_SET 0
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef SEEK_END
|
|
|
|
|
#define SEEK_END 2
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Inside the state file, the form-tree consists of a series of
|
|
|
|
|
form-tree entries (FTE's). The parent/child/sibling relationships
|
|
|
|
|
are implied by the ordering and by an explicit sibling reference
|
|
|
|
|
in FTE's that have siblings.
|
|
|
|
|
|
|
|
|
|
Specifically, given two sequential FTE's, say A and B, if B immediately
|
|
|
|
|
follows A, and A does not have a sibling reference to B, then B is
|
|
|
|
|
the first child of A. Otherwise B must be a sibling of A and A must
|
|
|
|
|
have a sibling reference for it.
|
|
|
|
|
|
|
|
|
|
Each FTE is simply an array of long integers, with at least three
|
|
|
|
|
members. This form was chosen over a packed data form for simplicity
|
|
|
|
|
in access, not having to worry about the relative sizes of the different
|
|
|
|
|
integers (short, int, long), and not having to worry about alignment
|
|
|
|
|
constraints. Also in the name of simplicity, every FTE has a sibling
|
|
|
|
|
reference slot reserved for it, even if there are no siblings.
|
|
|
|
|
|
|
|
|
|
The first value in an FTE is the size of the FTE in bytes, including
|
|
|
|
|
the size value itself. The second entry contains a tag which indicates
|
|
|
|
|
the type of the FTE. The third entry is a sibling reference, which either
|
|
|
|
|
refers to a valid sibling node or is zero. Following is zero or more
|
|
|
|
|
attributes, each of which consists of one or more long values. */
|
|
|
|
|
|
|
|
|
|
/* Tag names and codes. */
|
|
|
|
|
|
|
|
|
|
#define TAG_padding 0x0000 /* Padding */
|
|
|
|
|
#define TAG_objfile 0x0001 /* Dumped objfile */
|
|
|
|
|
|
|
|
|
|
/* Form names, codes, and macros. */
|
|
|
|
|
|
|
|
|
|
#define FORM_ABSREF 0x01 /* Next long is absolute file offset */
|
|
|
|
|
#define FORM_RELREF 0x02 /* Next long is relative file offset */
|
|
|
|
|
#define FORM_IVAL 0x03 /* Next long is int value */
|
|
|
|
|
#define FORM_ADDR 0x04 /* Next long is mem addr */
|
|
|
|
|
|
|
|
|
|
#define FORM_MASK 0xFF
|
|
|
|
|
#define FORM_X(atr) ((atr) & FORM_MASK)
|
|
|
|
|
|
|
|
|
|
/* Attribute names and codes. */
|
|
|
|
|
|
|
|
|
|
#define AT_sibling (0x0100 | FORM_RELREF) /* Reference to sibling node */
|
|
|
|
|
#define AT_name (0x0200 | FORM_ABSREF) /* Reference to a string */
|
|
|
|
|
#define AT_offset (0x0300 | FORM_ABSREF) /* Reference to generic data */
|
|
|
|
|
#define AT_size (0x0400 | FORM_IVAL)
|
|
|
|
|
#define AT_addr (0x0500 | FORM_ADDR)
|
|
|
|
|
#define AT_aux_addr (0x0600 | FORM_ADDR)
|
|
|
|
|
|
|
|
|
|
/* */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
load_symbols PARAMS ((FILE *));
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
dump_state_command PARAMS ((char *, int));
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
load_state_command PARAMS ((char *, int));
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_MMAP
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_header PARAMS ((sfd *));
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_formtree PARAMS ((sfd *));
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_objfile_state PARAMS ((sfd *));
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_subtree PARAMS ((struct formnode *));
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
size_subtree PARAMS ((struct formnode *));
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
struct formnode *formtree = NULL;
|
|
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
|
static void
|
|
|
|
|
load_symbols (statefile)
|
|
|
|
|
FILE *statefile;
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
/* Discard old symbols. FIXME: This is essentially symbol_file_command's
|
|
|
|
|
body when there is no name. Make it a common function that is
|
|
|
|
|
called from each place. */
|
|
|
|
|
|
|
|
|
|
if (symfile_objfile)
|
|
|
|
|
{
|
|
|
|
|
free_objfile (symfile_objfile);
|
|
|
|
|
}
|
|
|
|
|
symfile_objfile = NULL;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if 0 && defined (HAVE_MMAP)
|
|
|
|
|
if (mtop > mbase)
|
|
|
|
|
{
|
|
|
|
|
warning ("internal error: mbase (%08x) != mtop (%08x)",
|
|
|
|
|
mbase, mtop);
|
|
|
|
|
munmap (mbase, mtop - mbase);
|
|
|
|
|
}
|
|
|
|
|
#endif /* HAVE_MMAP */
|
|
|
|
|
|
|
|
|
|
/* Getting new symbols may change our opinion about what is frameless. */
|
|
|
|
|
|
|
|
|
|
reinit_frame_cache ();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_MMAP
|
|
|
|
|
|
|
|
|
|
/* Allocate a form node */
|
|
|
|
|
|
|
|
|
|
static struct formnode *
|
|
|
|
|
alloc_formnode ()
|
|
|
|
|
{
|
|
|
|
|
struct formnode *fnp;
|
|
|
|
|
fnp = (struct formnode *) xmalloc (sizeof (struct formnode));
|
|
|
|
|
(void) memset (fnp, 0, sizeof (struct formnode));
|
|
|
|
|
fnp -> sibling = formtree;
|
|
|
|
|
formtree = fnp;
|
|
|
|
|
return (fnp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Recursively walk a form-tree from the specified node, freeing
|
|
|
|
|
nodes from the bottom up. The concept is pretty simple, just free
|
|
|
|
|
all the child nodes, then all the sibling nodes, then the node
|
|
|
|
|
itself. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_subtree (fnp)
|
|
|
|
|
struct formnode *fnp;
|
|
|
|
|
{
|
|
|
|
|
if (fnp != NULL)
|
|
|
|
|
{
|
|
|
|
|
free_subtree (fnp -> child);
|
|
|
|
|
free_subtree (fnp -> sibling);
|
|
|
|
|
if (fnp -> nodedata != NULL)
|
|
|
|
|
{
|
|
|
|
|
free (fnp -> nodedata);
|
|
|
|
|
}
|
|
|
|
|
free (fnp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Recursively walk a form-tree from the specified node, computing the
|
|
|
|
|
size of each subtree from the bottom up.
|
|
|
|
|
|
|
|
|
|
At each node, the file space that will be consumed by the subtree
|
|
|
|
|
rooted in that node is the sum of all the subtrees rooted in each
|
|
|
|
|
child node plus the size of the node itself.
|
|
|
|
|
|
|
|
|
|
Thus for each node, we size the child subtrees, add to that our
|
|
|
|
|
size, contribute this size towards the size of any parent node, and
|
|
|
|
|
then ask any of our siblings to do the same.
|
|
|
|
|
|
|
|
|
|
Also, once we know the size of any subtree rooted at this node, we
|
|
|
|
|
can initialize the offset to the sibling node (if any).
|
|
|
|
|
|
|
|
|
|
Since every form-tree node must have valid nodedata at this point,
|
|
|
|
|
we detect and report a warning for any node that doesn't. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
size_subtree (fnp)
|
|
|
|
|
struct formnode *fnp;
|
|
|
|
|
{
|
|
|
|
|
long *lp;
|
|
|
|
|
|
|
|
|
|
if (fnp != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (fnp -> nodedata == NULL)
|
|
|
|
|
{
|
|
|
|
|
warning ("internal error -- empty form node");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
size_subtree (fnp -> child);
|
|
|
|
|
fnp -> treesize += *(long *) fnp -> nodedata;
|
|
|
|
|
if (fnp -> parent != NULL)
|
|
|
|
|
{
|
|
|
|
|
fnp -> parent -> treesize += fnp -> treesize;
|
|
|
|
|
}
|
|
|
|
|
if (fnp -> sibling)
|
|
|
|
|
{
|
|
|
|
|
size_subtree (fnp -> sibling);
|
|
|
|
|
lp = (long *) (fnp -> nodedata + 2 * sizeof (long));
|
|
|
|
|
*lp = fnp -> treesize;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Recursively walk a form-tree from the specified node, writing
|
|
|
|
|
nodes from the top down. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_subtree (fnp, asfd)
|
|
|
|
|
struct formnode *fnp;
|
|
|
|
|
sfd *asfd;
|
|
|
|
|
{
|
|
|
|
|
if (fnp != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (fnp -> nodedata != NULL)
|
|
|
|
|
{
|
|
|
|
|
fwrite (fnp -> nodedata, *(long *) fnp -> nodedata, 1, asfd -> fp);
|
|
|
|
|
}
|
|
|
|
|
write_subtree (fnp -> child, asfd);
|
|
|
|
|
write_subtree (fnp -> sibling, asfd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Free the entire current formtree. Called via do_cleanups, regardless
|
|
|
|
|
of whether there is an error or not. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
free_formtree ()
|
|
|
|
|
{
|
|
|
|
|
free_subtree (formtree);
|
|
|
|
|
formtree = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Write out the file header. Generally this is done last, even though
|
|
|
|
|
it is located at the start of the file, since we need to have file
|
|
|
|
|
offset to where the annotated form tree was written, and it's size. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_header (asfd)
|
|
|
|
|
sfd *asfd;
|
|
|
|
|
{
|
|
|
|
|
fseek (asfd -> fp, 0L, SEEK_SET);
|
|
|
|
|
fwrite ((char *) &asfd -> hdr, sizeof (asfd -> hdr), 1, asfd -> fp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Write out the annotated form tree. We should already have written out
|
|
|
|
|
the state data, and noted the file offsets and sizes in each node of
|
|
|
|
|
the form tree that references part of the state data.
|
|
|
|
|
|
|
|
|
|
The form tree can be written anywhere in the file where there is room
|
|
|
|
|
for it. Since there is always room at the end of the file, we write
|
|
|
|
|
it there. We also need to record the file offset to the start of the
|
|
|
|
|
form tree, and it's size, for future use when writing the file header.
|
|
|
|
|
|
|
|
|
|
In order to compute the sibling references, we need to know, at
|
|
|
|
|
each node, how much space will be consumed when all of that node's
|
|
|
|
|
children nodes have been written. Thus we walk the tree, computing
|
|
|
|
|
the sizes of the subtrees from the bottom up. At any node, the
|
|
|
|
|
offset from the start of that node to the start of the sibling node
|
|
|
|
|
is simply the size of the node plus the size of the subtree rooted
|
|
|
|
|
in that node. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_formtree (asfd)
|
|
|
|
|
sfd *asfd;
|
|
|
|
|
{
|
|
|
|
|
size_subtree (formtree);
|
|
|
|
|
fseek (asfd -> fp, 0L, SEEK_END);
|
|
|
|
|
asfd -> hdr.sf_ftoff = ftell (asfd -> fp);
|
|
|
|
|
write_subtree (formtree, asfd);
|
|
|
|
|
asfd -> hdr.sf_ftsize = ftell (asfd -> fp) - asfd -> hdr.sf_ftoff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Note that we currently only support having one objfile with dumpable
|
|
|
|
|
state. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
write_objfile_state (asfd)
|
|
|
|
|
sfd *asfd;
|
|
|
|
|
{
|
|
|
|
|
struct objfile *objfile;
|
|
|
|
|
struct formnode *fnp;
|
|
|
|
|
PTR base;
|
|
|
|
|
PTR breakval;
|
|
|
|
|
long *lp;
|
|
|
|
|
unsigned int ftesize;
|
|
|
|
|
long ftebuf[64];
|
|
|
|
|
long foffset;
|
|
|
|
|
|
|
|
|
|
/* First walk through the objfile list looking for the first objfile
|
|
|
|
|
that is dumpable. */
|
|
|
|
|
|
|
|
|
|
for (objfile = object_files; objfile != NULL; objfile = objfile -> next)
|
|
|
|
|
{
|
|
|
|
|
if (objfile -> flags & OBJF_DUMPABLE)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (objfile == NULL)
|
|
|
|
|
{
|
|
|
|
|
warning ("no dumpable objfile was found");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fnp = alloc_formnode ();
|
|
|
|
|
lp = ftebuf;
|
|
|
|
|
|
|
|
|
|
lp++; /* Skip FTE size slot, filled in at the end. */
|
|
|
|
|
*lp++ = TAG_objfile; /* This is an objfile FTE */
|
|
|
|
|
*lp++ = 0; /* Zero the sibling reference slot. */
|
|
|
|
|
|
|
|
|
|
/* Build an AT_name attribute for the objfile's name, and write
|
|
|
|
|
the name into the state data. */
|
|
|
|
|
|
|
|
|
|
*lp++ = AT_name;
|
|
|
|
|
*lp++ = (long) ftell (asfd -> fp);
|
|
|
|
|
fwrite (objfile -> name, strlen (objfile -> name) + 1, 1, asfd -> fp);
|
|
|
|
|
|
|
|
|
|
/* Build an AT_addr attribute for the virtual address to which the
|
|
|
|
|
objfile data is mapped (and needs to be remapped when read in). */
|
|
|
|
|
|
|
|
|
|
base = mmap_base ();
|
|
|
|
|
*lp++ = AT_addr;
|
|
|
|
|
*lp++ = (long) base;
|
|
|
|
|
|
|
|
|
|
/* Build an AT_aux_addr attribute for the address of the objfile
|
|
|
|
|
structure itself, within the dumpable data. When we read the objfile
|
|
|
|
|
back in, we use this address as the pointer the "struct objfile". */
|
|
|
|
|
|
|
|
|
|
*lp++ = AT_aux_addr;
|
|
|
|
|
*lp++ = (long) objfile;
|
|
|
|
|
|
|
|
|
|
/* Reposition in state file to next paging boundry so we can mmap the
|
|
|
|
|
dumpable objfile data when we reload it. */
|
|
|
|
|
|
|
|
|
|
foffset = (long) mmap_page_align ((PTR) ftell (asfd -> fp));
|
|
|
|
|
fseek (asfd -> fp, foffset, SEEK_SET);
|
|
|
|
|
|
|
|
|
|
/* Build an AT_offset attribute for the offset in the state file to
|
|
|
|
|
the start of the dumped objfile data. */
|
|
|
|
|
|
|
|
|
|
*lp++ = AT_offset;
|
|
|
|
|
*lp++ = (long) ftell (asfd -> fp);
|
|
|
|
|
|
|
|
|
|
/* Build an AT_size attribute for the size of the dumped objfile data. */
|
|
|
|
|
|
|
|
|
|
breakval = mmap_sbrk (0);
|
|
|
|
|
*lp++ = AT_size;
|
|
|
|
|
*lp++ = breakval - base;
|
|
|
|
|
|
|
|
|
|
/* Write the dumpable data. */
|
|
|
|
|
|
|
|
|
|
fwrite ((char *) base, breakval - base, 1, asfd -> fp);
|
|
|
|
|
|
|
|
|
|
/* Now finish up the FTE by filling in the size slot based on
|
|
|
|
|
how much of the ftebuf we have used, allocate some memory for
|
|
|
|
|
it hung off the form tree node, and copy it there. */
|
|
|
|
|
|
|
|
|
|
ftebuf[0] = (lp - ftebuf) * sizeof (ftebuf[0]);
|
|
|
|
|
fnp -> nodedata = (char *) xmalloc (ftebuf[0]);
|
|
|
|
|
memcpy (fnp -> nodedata, ftebuf, ftebuf[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
load_state_command (arg_string, from_tty)
|
|
|
|
|
char *arg_string;
|
|
|
|
|
int from_tty;
|
|
|
|
|
{
|
|
|
|
|
char *filename;
|
|
|
|
|
char **argv;
|
|
|
|
|
FILE *fp;
|
|
|
|
|
struct cleanup *cleanups;
|
|
|
|
|
|
|
|
|
|
dont_repeat ();
|
|
|
|
|
|
|
|
|
|
if (arg_string == NULL)
|
|
|
|
|
{
|
|
|
|
|
error ("load-state takes a file name and optional state specifiers");
|
|
|
|
|
}
|
|
|
|
|
else if ((argv = buildargv (arg_string)) == NULL)
|
|
|
|
|
{
|
|
|
|
|
fatal ("virtual memory exhausted.", 0);
|
|
|
|
|
}
|
|
|
|
|
cleanups = make_cleanup (freeargv, argv);
|
|
|
|
|
|
|
|
|
|
filename = tilde_expand (*argv);
|
|
|
|
|
make_cleanup (free, filename);
|
|
|
|
|
|
1993-01-07 02:22:01 +08:00
|
|
|
|
if ((fp = fopen (filename, FOPEN_RB)) == NULL)
|
1992-02-22 09:46:16 +08:00
|
|
|
|
{
|
|
|
|
|
perror_with_name (filename);
|
|
|
|
|
}
|
|
|
|
|
make_cleanup (fclose, fp);
|
|
|
|
|
immediate_quit++;
|
|
|
|
|
|
|
|
|
|
while (*++argv != NULL)
|
|
|
|
|
{
|
* defs.h (STRCMP, STREQ, STREQN): New macros.
* defs.h (demangle_and_match): Remove prototype.
* dwarfread.c (STREQ, STREQN): Remove macros, replaced with STREQ
and STREQN defined in defs.h.
* dwarfread.c (set_cu_language): For completely unknown languages,
try to deduce the language from the filename. Retain behavior
that for known languages we don't know how to handle, we use
language_unknown.
* dwarfread.c (enum_type, symthesize_typedef): Initialize language
and demangled name fields in symbol.
* dwarfread.c, mipsread.c, partial-stab.h: For all usages of
ADD_PSYMBOL_TO_LIST, add language and objfile parameters.
* dwarfread.c (new_symbol): Attempt to demangle C++ symbol names
and cache the results in SYMBOL_DEMANGLED_NAME for the symbol.
* elfread.c (STREQ): Remove macro, use STREQ defined in defs.h.
Replace usages throughout.
* elfread.c (demangle.h): Include.
* elfread.c (record_minimal_symbol): Remove prototype and function.
* gdbtypes.h, symtab.h (B_SET, B_CLR, B_TST, B_TYPE, B_BYTES,
B_CLRALL): Moved from symtab.h to gdbtypes.h.
* infcmd.c (jump_command): Remove code to demangle name and add
it to a cleanup list. Now just use SYMBOL_DEMANGLED_NAME.
* minsyms.c (demangle.h): Include.
* minsyms.c (lookup_minimal_symbol): Indent comment to match code.
* minsyms.c (install_minimal_symbols): Attempt to demangle symbol
names as C++ names, and cache them in SYMBOL_DEMANGLED_NAME.
* mipsread.c (psymtab_language): Add static variable.
* stabsread.c (demangle.h): Include.
* stabsread.c (define_symbol): Attempt to demangle C++ symbol
names and cache them in the SYMBOL_DEMANGLED_NAME field.
* stack.c (return_command): Remove explicit demangling of name
and use of cleanups. Just use SYMBOL_DEMANGLED_NAME.
* symfile.c (demangle.h): Include.
* symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list): Fix
to match macros in symfile.h and allow them to be compiled
if INLINE_ADD_PSYMBOL is not true.
* symfile.h (INLINE_ADD_PSYMBOL): Default to true if not set.
* symfile.h (ADD_PSYMBOL_*): Add language and objfile parameters.
Add code to demangle and cache C++ symbol names. Use macro form
if INLINE_ADD_PSYMBOL is true, otherwise use C function form.
* symmisc.c (add_psymbol_to_list, add_psymbol_addr_to_list):
Remove, also defined in symfile.c, which we already fixed.
* symtab.c (expensive_mangler): Remove prototype and function.
* symtab.c (find_methods): Remove physnames parameter and fix
prototype to match.
* symtab.c (completion_list_add_symbol): Name changed to
completion_list_add_name.
* symtab.c (COMPLETION_LIST_ADD_SYMBOL): New macro, adds both
the normal symbol name and the cached C++ demangled name.
* symtab.c (lookup_demangled_partial_symbol,
lookup_demangled_block_symbol): Remove prototypes and functions.
* symtab.c (lookup_symbol): Remove use of expensive_mangler,
use lookup_block_symbol instead of lookup_demangled_block_symbol.
Remove code to try demangling names and matching them.
* symtab.c (lookup_partial_symbol, lookup_block_symbol):
Fix to try matching the cached demangled name if no match is
found using the regular symbol name.
* symtab.c (find_methods): Remove unused physnames array.
* symtab.c (name_match, NAME_MATCH): Remove function and macro,
replaced with SYMBOL_MATCHES_REGEXP from symtab.h.
* symtab.c (completion_list_add_symbol): Rewrite to use cached
C++ demangled symbol names.
* symtab.h: Much reformatting of structures and such to add
whitespace to make them more readable, and make them more
consistent with other gdb structure definitions.
* symtab.h (general_symbol_info): New struct containing fields
common to all symbols.
* symtab.h (SYMBOL_LANGUAGE, SYMBOL_DEMANGLED_NAME,
SYMBOL_SOURCE_NAME, SYMBOL_LINKAGE_NAME, SYMBOL_MATCHES_NAME,
SYMBOL_MATCHES_REGEXP, MSYMBOL_INFO, MSYMBOL_TYPE): New macros.
* symtab. (struct minimal_symbol, struct partial_symbol, struct
symbol): Use general_symbol_info struct.
* utils.c (demangle_and_match): Remove, no longer used.
* valops.c (demangle.h): Include.
* xcoffexec.c (eq): Remove macro, replace usages with STREQ.
* blockframe.c, breakpoint.c, c-exp.y, c-valprint.c, dbxread.c,
infcmd.c, m2-exp.y, minsyms.c, objfiles.h, solib.c, stack.c,
symmisc.c, symtab.c, valops.c: Replace references to minimal
symbol fields with appropriate macros.
* breakpoint.c, buildsym.c, c-exp.y, c-typeprint.c, c-valprint.c,
coffread.c, command.c, convex-tdep.c, cp-valprint.c, dbxread.c,
demangle.c, elfread.c, energize.c, environ.c, exec.c,
gdbtypes.c, i960-tdep.c, infrun.c, infrun-hacked.c, language.c,
main.c, minsyms.c, mipsread.c, partial-stab.h, remote-es1800.c,
remote-nindy.c, remote-udi.c, rs6000-tdep.c, solib.c, source.c,
sparc-pinsn.c, stabsread.c, standalone.c, state.c, stuff.c,
symfile.c, symmisc.c, symtab.c, symtab.h, tm-sysv4.h,
tm-ultra3.h, values.c, xcoffexec.c, xcoffread.c: Replace strcmp
and strncmp usages with STREQ, STREQN, or STRCMP as appropriate.
* breakpoint.c, buildsym.c, c-typeprint.c, expprint.c, findvar.c,
mipsread.c, printcmd.c, source.c, stabsread.c, stack.c,
symmisc.c, tm-29k.h, valops.c, values.c: Replace SYMBOL_NAME
references with SYMBOL_SOURCE_NAME or SYMBOL_LINKAGE_NAME as
appropriate.
* buildsym.c (start_subfile, patch_subfile_names): Default the
source language to what can be deduced from the filename.
* buildsym.c (end_symtab): Update the source language in the
allocated symtab to match what we have been using.
* buildsym.h (struct subfile): Add a language field.
* c-typeprint.c (c_print_type): Remove code to do explicit
demangling.
* dbxread.c (psymtab_language): Add static variable.
* dbxread.c (start_psymtab): Initialize psymtab_language using
deduce_language_from_filename.
1992-12-23 14:34:57 +08:00
|
|
|
|
if (STREQ (*argv, "symbols"))
|
1992-02-22 09:46:16 +08:00
|
|
|
|
{
|
|
|
|
|
if (from_tty
|
|
|
|
|
&& !query ("load symbol table state from file \"%s\"? ",
|
|
|
|
|
filename))
|
|
|
|
|
{
|
|
|
|
|
error ("Not confirmed.");
|
|
|
|
|
}
|
|
|
|
|
load_symbols (fp);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
error ("unknown state specifier '%s'", *argv);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
immediate_quit--;
|
|
|
|
|
do_cleanups (cleanups);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
|
static void
|
|
|
|
|
dump_state_command (arg_string, from_tty)
|
|
|
|
|
char *arg_string;
|
|
|
|
|
int from_tty;
|
|
|
|
|
{
|
|
|
|
|
char *filename;
|
|
|
|
|
char **argv;
|
|
|
|
|
sfd *asfd;
|
|
|
|
|
struct cleanup *cleanups;
|
|
|
|
|
|
|
|
|
|
dont_repeat ();
|
|
|
|
|
|
|
|
|
|
if (arg_string == NULL)
|
|
|
|
|
{
|
|
|
|
|
error ("dump-state takes a file name and state specifiers");
|
|
|
|
|
}
|
|
|
|
|
else if ((argv = buildargv (arg_string)) == NULL)
|
|
|
|
|
{
|
|
|
|
|
fatal ("virtual memory exhausted.", 0);
|
|
|
|
|
}
|
|
|
|
|
cleanups = make_cleanup (freeargv, argv);
|
|
|
|
|
|
|
|
|
|
filename = tilde_expand (*argv);
|
|
|
|
|
make_cleanup (free, filename);
|
|
|
|
|
|
|
|
|
|
/* Now attempt to create a fresh state file. */
|
|
|
|
|
|
1993-01-07 02:22:01 +08:00
|
|
|
|
if ((asfd = sfd_fopen (filename, FOPEN_WB)) == NULL)
|
1992-02-22 09:46:16 +08:00
|
|
|
|
{
|
|
|
|
|
perror_with_name (filename);
|
|
|
|
|
}
|
|
|
|
|
make_cleanup (sfd_fclose, asfd);
|
|
|
|
|
make_cleanup (free_formtree, NULL);
|
|
|
|
|
immediate_quit++;
|
|
|
|
|
|
|
|
|
|
/* Now that we have an open and initialized state file, seek to the
|
|
|
|
|
proper offset to start writing state data and the process the
|
|
|
|
|
arguments. For each argument, write the state data and initialize
|
|
|
|
|
a form-tree node for each piece of state data. */
|
|
|
|
|
|
|
|
|
|
fseek (asfd -> fp, sizeof (sf_hdr), SEEK_SET);
|
|
|
|
|
while (*++argv != NULL)
|
|
|
|
|
{
|
* defs.h (STRCMP, STREQ, STREQN): New macros.
* defs.h (demangle_and_match): Remove prototype.
* dwarfread.c (STREQ, STREQN): Remove macros, replaced with STREQ
and STREQN defined in defs.h.
* dwarfread.c (set_cu_language): For completely unknown languages,
try to deduce the language from the filename. Retain behavior
that for known languages we don't know how to handle, we use
language_unknown.
* dwarfread.c (enum_type, symthesize_typedef): Initialize language
and demangled name fields in symbol.
* dwarfread.c, mipsread.c, partial-stab.h: For all usages of
ADD_PSYMBOL_TO_LIST, add language and objfile parameters.
* dwarfread.c (new_symbol): Attempt to demangle C++ symbol names
and cache the results in SYMBOL_DEMANGLED_NAME for the symbol.
* elfread.c (STREQ): Remove macro, use STREQ defined in defs.h.
Replace usages throughout.
* elfread.c (demangle.h): Include.
* elfread.c (record_minimal_symbol): Remove prototype and function.
* gdbtypes.h, symtab.h (B_SET, B_CLR, B_TST, B_TYPE, B_BYTES,
B_CLRALL): Moved from symtab.h to gdbtypes.h.
* infcmd.c (jump_command): Remove code to demangle name and add
it to a cleanup list. Now just use SYMBOL_DEMANGLED_NAME.
* minsyms.c (demangle.h): Include.
* minsyms.c (lookup_minimal_symbol): Indent comment to match code.
* minsyms.c (install_minimal_symbols): Attempt to demangle symbol
names as C++ names, and cache them in SYMBOL_DEMANGLED_NAME.
* mipsread.c (psymtab_language): Add static variable.
* stabsread.c (demangle.h): Include.
* stabsread.c (define_symbol): Attempt to demangle C++ symbol
names and cache them in the SYMBOL_DEMANGLED_NAME field.
* stack.c (return_command): Remove explicit demangling of name
and use of cleanups. Just use SYMBOL_DEMANGLED_NAME.
* symfile.c (demangle.h): Include.
* symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list): Fix
to match macros in symfile.h and allow them to be compiled
if INLINE_ADD_PSYMBOL is not true.
* symfile.h (INLINE_ADD_PSYMBOL): Default to true if not set.
* symfile.h (ADD_PSYMBOL_*): Add language and objfile parameters.
Add code to demangle and cache C++ symbol names. Use macro form
if INLINE_ADD_PSYMBOL is true, otherwise use C function form.
* symmisc.c (add_psymbol_to_list, add_psymbol_addr_to_list):
Remove, also defined in symfile.c, which we already fixed.
* symtab.c (expensive_mangler): Remove prototype and function.
* symtab.c (find_methods): Remove physnames parameter and fix
prototype to match.
* symtab.c (completion_list_add_symbol): Name changed to
completion_list_add_name.
* symtab.c (COMPLETION_LIST_ADD_SYMBOL): New macro, adds both
the normal symbol name and the cached C++ demangled name.
* symtab.c (lookup_demangled_partial_symbol,
lookup_demangled_block_symbol): Remove prototypes and functions.
* symtab.c (lookup_symbol): Remove use of expensive_mangler,
use lookup_block_symbol instead of lookup_demangled_block_symbol.
Remove code to try demangling names and matching them.
* symtab.c (lookup_partial_symbol, lookup_block_symbol):
Fix to try matching the cached demangled name if no match is
found using the regular symbol name.
* symtab.c (find_methods): Remove unused physnames array.
* symtab.c (name_match, NAME_MATCH): Remove function and macro,
replaced with SYMBOL_MATCHES_REGEXP from symtab.h.
* symtab.c (completion_list_add_symbol): Rewrite to use cached
C++ demangled symbol names.
* symtab.h: Much reformatting of structures and such to add
whitespace to make them more readable, and make them more
consistent with other gdb structure definitions.
* symtab.h (general_symbol_info): New struct containing fields
common to all symbols.
* symtab.h (SYMBOL_LANGUAGE, SYMBOL_DEMANGLED_NAME,
SYMBOL_SOURCE_NAME, SYMBOL_LINKAGE_NAME, SYMBOL_MATCHES_NAME,
SYMBOL_MATCHES_REGEXP, MSYMBOL_INFO, MSYMBOL_TYPE): New macros.
* symtab. (struct minimal_symbol, struct partial_symbol, struct
symbol): Use general_symbol_info struct.
* utils.c (demangle_and_match): Remove, no longer used.
* valops.c (demangle.h): Include.
* xcoffexec.c (eq): Remove macro, replace usages with STREQ.
* blockframe.c, breakpoint.c, c-exp.y, c-valprint.c, dbxread.c,
infcmd.c, m2-exp.y, minsyms.c, objfiles.h, solib.c, stack.c,
symmisc.c, symtab.c, valops.c: Replace references to minimal
symbol fields with appropriate macros.
* breakpoint.c, buildsym.c, c-exp.y, c-typeprint.c, c-valprint.c,
coffread.c, command.c, convex-tdep.c, cp-valprint.c, dbxread.c,
demangle.c, elfread.c, energize.c, environ.c, exec.c,
gdbtypes.c, i960-tdep.c, infrun.c, infrun-hacked.c, language.c,
main.c, minsyms.c, mipsread.c, partial-stab.h, remote-es1800.c,
remote-nindy.c, remote-udi.c, rs6000-tdep.c, solib.c, source.c,
sparc-pinsn.c, stabsread.c, standalone.c, state.c, stuff.c,
symfile.c, symmisc.c, symtab.c, symtab.h, tm-sysv4.h,
tm-ultra3.h, values.c, xcoffexec.c, xcoffread.c: Replace strcmp
and strncmp usages with STREQ, STREQN, or STRCMP as appropriate.
* breakpoint.c, buildsym.c, c-typeprint.c, expprint.c, findvar.c,
mipsread.c, printcmd.c, source.c, stabsread.c, stack.c,
symmisc.c, tm-29k.h, valops.c, values.c: Replace SYMBOL_NAME
references with SYMBOL_SOURCE_NAME or SYMBOL_LINKAGE_NAME as
appropriate.
* buildsym.c (start_subfile, patch_subfile_names): Default the
source language to what can be deduced from the filename.
* buildsym.c (end_symtab): Update the source language in the
allocated symtab to match what we have been using.
* buildsym.h (struct subfile): Add a language field.
* c-typeprint.c (c_print_type): Remove code to do explicit
demangling.
* dbxread.c (psymtab_language): Add static variable.
* dbxread.c (start_psymtab): Initialize psymtab_language using
deduce_language_from_filename.
1992-12-23 14:34:57 +08:00
|
|
|
|
if (STREQ (*argv, "objfile"))
|
1992-02-22 09:46:16 +08:00
|
|
|
|
{
|
|
|
|
|
write_objfile_state (asfd);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
error ("unknown state specifier '%s'", *argv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We have written any state data. All that is left to do now is
|
|
|
|
|
write the form-tree and the file header. */
|
|
|
|
|
|
|
|
|
|
write_formtree (asfd);
|
|
|
|
|
write_header (asfd);
|
|
|
|
|
|
|
|
|
|
immediate_quit--;
|
|
|
|
|
do_cleanups (cleanups);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
find_fte_by_walk (thisfte, endfte, tag)
|
|
|
|
|
char *thisfte;
|
|
|
|
|
char *endfte;
|
|
|
|
|
long tag;
|
|
|
|
|
{
|
|
|
|
|
char *found = NULL;
|
|
|
|
|
char *nextfte;
|
|
|
|
|
long thistag;
|
|
|
|
|
long thissize;
|
|
|
|
|
long siboffset;
|
|
|
|
|
|
|
|
|
|
while (thisfte < endfte)
|
|
|
|
|
{
|
|
|
|
|
if ((thistag = *(long *)(thisfte + sizeof (long))) == tag)
|
|
|
|
|
{
|
|
|
|
|
found = thisfte;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
thissize = *(long *)(thisfte);
|
|
|
|
|
siboffset = *(long *)(thisfte + (2 * sizeof (long)));
|
|
|
|
|
nextfte = thisfte + (siboffset != 0 ? siboffset : thissize);
|
|
|
|
|
found = find_fte_by_walk (thisfte + thissize, nextfte, tag);
|
|
|
|
|
thisfte = nextfte;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (found);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Walk the form-tree looking for a specific FTE type. Returns the first
|
|
|
|
|
one found that matches the specified tag. */
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
find_fte (asfd, tag)
|
|
|
|
|
sfd *asfd;
|
|
|
|
|
long tag;
|
|
|
|
|
{
|
|
|
|
|
char *ftbase;
|
|
|
|
|
char *ftend;
|
|
|
|
|
char *ftep;
|
|
|
|
|
char *found = NULL;
|
|
|
|
|
|
|
|
|
|
if (fseek (asfd -> fp, asfd -> hdr.sf_ftoff, SEEK_SET) == 0)
|
|
|
|
|
{
|
|
|
|
|
ftbase = xmalloc (asfd -> hdr.sf_ftsize);
|
|
|
|
|
ftend = ftbase + asfd -> hdr.sf_ftsize;
|
|
|
|
|
if (fread (ftbase, asfd -> hdr.sf_ftsize, 1, asfd -> fp) == 1)
|
|
|
|
|
{
|
|
|
|
|
ftep = find_fte_by_walk (ftbase, ftend, tag);
|
|
|
|
|
if (ftep != NULL)
|
|
|
|
|
{
|
|
|
|
|
found = xmalloc (*(long *)ftep);
|
|
|
|
|
memcpy (found, ftep, (int) *(long *)ftep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free (ftbase);
|
|
|
|
|
}
|
|
|
|
|
return (found);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct objfile *
|
|
|
|
|
objfile_from_statefile (asfd)
|
|
|
|
|
sfd *asfd;
|
|
|
|
|
{
|
|
|
|
|
struct objfile *objfile = NULL;
|
|
|
|
|
char *ftep;
|
|
|
|
|
long *thisattr;
|
|
|
|
|
long *endattr;
|
|
|
|
|
PTR base;
|
|
|
|
|
long foffset;
|
|
|
|
|
long mapsize;
|
|
|
|
|
|
|
|
|
|
ftep = find_fte (asfd, TAG_objfile);
|
|
|
|
|
thisattr = (long *) (ftep + 3 * sizeof (long));
|
|
|
|
|
endattr = (long *) (ftep + *(long *)ftep);
|
|
|
|
|
while (thisattr < endattr)
|
|
|
|
|
{
|
|
|
|
|
switch (*thisattr++)
|
|
|
|
|
{
|
|
|
|
|
case AT_name:
|
|
|
|
|
/* Ignore for now */
|
|
|
|
|
thisattr++;
|
|
|
|
|
break;
|
|
|
|
|
case AT_addr:
|
|
|
|
|
base = (PTR) *thisattr++;
|
|
|
|
|
break;
|
|
|
|
|
case AT_aux_addr:
|
|
|
|
|
objfile = (struct objfile *) *thisattr++;
|
|
|
|
|
break;
|
|
|
|
|
case AT_offset:
|
|
|
|
|
foffset = *thisattr++;
|
|
|
|
|
break;
|
|
|
|
|
case AT_size:
|
|
|
|
|
mapsize = *thisattr++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (mmap_remap (base, mapsize, (int) fileno (asfd -> fp), foffset) != base)
|
|
|
|
|
{
|
|
|
|
|
print_sys_errmsg (asfd -> filename, errno);
|
|
|
|
|
error ("mapping failed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (objfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
struct objfile *
|
|
|
|
|
objfile_from_statefile (asfd)
|
|
|
|
|
sfd *asfd;
|
|
|
|
|
{
|
|
|
|
|
error ("this version of gdb doesn't support reloading symtabs from state files");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* HAVE_MMAP */
|
|
|
|
|
|
|
|
|
|
/* Close a state file, freeing all memory that was used by the state
|
|
|
|
|
file descriptor, closing the raw file pointer, etc. */
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
sfd_fclose (asfd)
|
|
|
|
|
sfd *asfd;
|
|
|
|
|
{
|
|
|
|
|
if (asfd != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (asfd -> fp != NULL)
|
|
|
|
|
{
|
|
|
|
|
fclose (asfd -> fp);
|
|
|
|
|
}
|
|
|
|
|
if (asfd -> filename != NULL)
|
|
|
|
|
{
|
|
|
|
|
free (asfd -> filename);
|
|
|
|
|
}
|
|
|
|
|
free (asfd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given the name of a possible statefile, and flags to use to open it,
|
|
|
|
|
try to open the file and prepare it for use.
|
|
|
|
|
|
|
|
|
|
If the flags contain 'r', then we want to read an existing state
|
|
|
|
|
file, so attempt to read in the state file header and determine if this
|
|
|
|
|
is a valid state file. If not, return NULL.
|
|
|
|
|
|
|
|
|
|
Returns a pointer to a properly initialized state file descriptor if
|
|
|
|
|
successful. */
|
|
|
|
|
|
|
|
|
|
sfd *
|
|
|
|
|
sfd_fopen (name, flags)
|
|
|
|
|
char *name;
|
|
|
|
|
char *flags;
|
|
|
|
|
{
|
|
|
|
|
int success = 0;
|
|
|
|
|
sfd *asfd;
|
|
|
|
|
|
|
|
|
|
asfd = (sfd *) xmalloc (sizeof (sfd));
|
|
|
|
|
(void) memset (asfd, 0, sizeof (sfd));
|
|
|
|
|
asfd -> filename = xmalloc (strlen (name) + 1);
|
|
|
|
|
(void) strcpy (asfd -> filename, name);
|
|
|
|
|
|
|
|
|
|
if ((asfd -> fp = fopen (asfd -> filename, flags)) != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* We have the file, now see if we are reading an existing file
|
|
|
|
|
or writing to a new file. We don't currently support "rw". */
|
|
|
|
|
if (strchr (flags, 'r') != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (fread ((char *) &asfd -> hdr, sizeof (asfd -> hdr), 1,
|
|
|
|
|
asfd -> fp) == 1)
|
|
|
|
|
{
|
|
|
|
|
if (SF_GOOD_MAGIC (asfd))
|
|
|
|
|
{
|
|
|
|
|
success = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* This is a new state file. Initialize various things. */
|
|
|
|
|
asfd -> hdr.sf_mag0 = SF_MAG0;
|
|
|
|
|
asfd -> hdr.sf_mag1 = SF_MAG1;
|
|
|
|
|
asfd -> hdr.sf_mag2 = SF_MAG2;
|
|
|
|
|
asfd -> hdr.sf_mag3 = SF_MAG3;
|
|
|
|
|
success = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!success)
|
|
|
|
|
{
|
|
|
|
|
sfd_fclose (asfd);
|
|
|
|
|
asfd = NULL;
|
|
|
|
|
}
|
|
|
|
|
return (asfd);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_initialize_state ()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_MMAP
|
|
|
|
|
|
|
|
|
|
add_com ("load-state", class_support, load_state_command,
|
|
|
|
|
"Load some saved gdb state from FILE.\n\
|
|
|
|
|
Select and load some portion of gdb's saved state from the specified file.\n\
|
|
|
|
|
The dump-state command may be used to save various portions of gdb's\n\
|
|
|
|
|
internal state.");
|
|
|
|
|
|
|
|
|
|
add_com ("dump-state", class_support, dump_state_command,
|
|
|
|
|
"Dump some of gdb's state to FILE.\n\
|
|
|
|
|
Select and dump some portion of gdb's internal state to the specified file.\n\
|
|
|
|
|
The load-state command may be used to reload various portions of gdb's\n\
|
|
|
|
|
internal state from the file.");
|
|
|
|
|
|
|
|
|
|
#endif /* HAVE_MMAP */
|
|
|
|
|
|
|
|
|
|
}
|