Blasting old junk
This commit is contained in:
parent
dea16e4dba
commit
19405856a1
7 changed files with 0 additions and 6820 deletions
1749
gdb/energize-patches
1749
gdb/energize-patches
File diff suppressed because it is too large
Load diff
1716
gdb/energize.c
1716
gdb/energize.c
File diff suppressed because it is too large
Load diff
|
@ -1,92 +0,0 @@
|
|||
/* Energize interface defs for GDB.
|
||||
Copyright (C) 1992 Free Software Foundation, Inc.
|
||||
|
||||
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. */
|
||||
|
||||
#if !defined (ENERGIZE_H)
|
||||
#define ENERGIZE_H 1
|
||||
|
||||
#ifdef __STDC__
|
||||
struct cmd_list_element;
|
||||
struct symbol;
|
||||
struct type;
|
||||
struct objfile;
|
||||
struct breakpoint;
|
||||
#endif /* __STDC__ */
|
||||
|
||||
/* Non-zero means that we're doing the energize interface. */
|
||||
extern int energize;
|
||||
|
||||
/* Get a pty for use with energize */
|
||||
extern char *energize_getpty PARAMS ((void));
|
||||
|
||||
/* Notify energize of new process creation */
|
||||
extern void energize_new_process PARAMS ((void));
|
||||
|
||||
/* Low level wait routine for wait_for_inferior */
|
||||
extern int energize_wait PARAMS ((int *));
|
||||
|
||||
/* Wait routine for processes spawned by the shell command */
|
||||
extern int energize_shell_wait PARAMS ((int *statusp));
|
||||
|
||||
/* Initialize */
|
||||
extern void energize_initialize PARAMS ((char *, char *));
|
||||
|
||||
/* Main loop for energize protocol driver */
|
||||
extern void energize_main_loop PARAMS ((void));
|
||||
|
||||
/* Command hook for energize */
|
||||
extern void energize_call_command PARAMS ((struct cmd_list_element *,
|
||||
char *, int));
|
||||
|
||||
/* Read commands for the command command, and others */
|
||||
extern char *energize_command_line_input PARAMS ((char *, int));
|
||||
|
||||
extern void energize_start_variable_annotation PARAMS ((char *,
|
||||
struct symbol *,
|
||||
struct type *,
|
||||
CORE_ADDR,
|
||||
char *));
|
||||
|
||||
extern void energize_end_variable_annotation PARAMS ((void));
|
||||
|
||||
extern void energize_annotate_function PARAMS ((char *, int, int));
|
||||
|
||||
extern void energize_symbol_file PARAMS ((struct objfile *));
|
||||
|
||||
/*extern void energize_query PARAMS ((char *, ...));*/
|
||||
extern void energize_query (); /* Prototypes for varargs don't work */
|
||||
|
||||
extern void energize_acknowledge_query PARAMS ((char *));
|
||||
|
||||
extern void energize_fputs PARAMS ((const char *));
|
||||
|
||||
extern void energize_condition_breakpoint PARAMS ((struct breakpoint *));
|
||||
|
||||
extern void energize_commands_breakpoint PARAMS ((struct breakpoint *));
|
||||
|
||||
extern void energize_ignore_breakpoint PARAMS ((struct breakpoint *));
|
||||
|
||||
extern void energize_create_breakpoint PARAMS ((struct breakpoint *));
|
||||
|
||||
extern void energize_delete_breakpoint PARAMS ((struct breakpoint *));
|
||||
|
||||
extern void energize_enable_breakpoint PARAMS ((struct breakpoint *));
|
||||
|
||||
extern void energize_disable_breakpoint PARAMS ((struct breakpoint *));
|
||||
|
||||
#endif /* !defined (ENERGIZE_H) */
|
1259
gdb/remote-mon.c
1259
gdb/remote-mon.c
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
775
gdb/state.c
775
gdb/state.c
|
@ -1,775 +0,0 @@
|
|||
/* 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);
|
||||
|
||||
if ((fp = fopen (filename, FOPEN_RB)) == NULL)
|
||||
{
|
||||
perror_with_name (filename);
|
||||
}
|
||||
make_cleanup (fclose, fp);
|
||||
immediate_quit++;
|
||||
|
||||
while (*++argv != NULL)
|
||||
{
|
||||
if (STREQ (*argv, "symbols"))
|
||||
{
|
||||
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. */
|
||||
|
||||
if ((asfd = sfd_fopen (filename, FOPEN_WB)) == NULL)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (STREQ (*argv, "objfile"))
|
||||
{
|
||||
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 */
|
||||
|
||||
}
|
85
gdb/state.h
85
gdb/state.h
|
@ -1,85 +0,0 @@
|
|||
/* 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 definitions used for reading and writing gdb
|
||||
state files. State files have a fairly simple form which is intended
|
||||
to be easily extensible. See state.c for further documentation. */
|
||||
|
||||
#if !defined (_STATE_H)
|
||||
#define _STATE_H
|
||||
|
||||
/* State file-header */
|
||||
|
||||
typedef struct {
|
||||
unsigned char sf_mag0; /* Magic number byte 0 */
|
||||
unsigned char sf_mag1; /* Magic number byte 1 */
|
||||
unsigned char sf_mag2; /* Magic number byte 2 */
|
||||
unsigned char sf_mag3; /* Magic number byte 3 */
|
||||
unsigned long sf_ftoff; /* File offset to start of form-tree */
|
||||
unsigned long sf_ftsize; /* Size of the form-tree, in bytes */
|
||||
} sf_hdr;
|
||||
|
||||
|
||||
#define SF_MAG0 'g' /* Magic number byte 0 value */
|
||||
#define SF_MAG1 'd' /* Magic number byte 1 value */
|
||||
#define SF_MAG2 'b' /* Magic number byte 2 value */
|
||||
#define SF_MAG3 '\000' /* Magic number byte 3 value */
|
||||
|
||||
#define SF_GOOD_MAGIC(asfd) ((asfd) -> hdr.sf_mag0 == SF_MAG0 && \
|
||||
(asfd) -> hdr.sf_mag1 == SF_MAG1 && \
|
||||
(asfd) -> hdr.sf_mag2 == SF_MAG2 && \
|
||||
(asfd) -> hdr.sf_mag3 == SF_MAG3)
|
||||
|
||||
/* The internal form-tree is formed from nodes that contain pointers
|
||||
to the first sibling, the first child, a backpointer to the parent,
|
||||
and a pointer to the actual data for the node. This allows all
|
||||
tree nodes to have the same sized structure, but support variable
|
||||
numbers of child nodes per parent node. The backpointer for the
|
||||
parent is required for simplier tree walks. */
|
||||
|
||||
struct formnode
|
||||
{
|
||||
struct formnode *sibling; /* Pointer to first sibling */
|
||||
struct formnode *child; /* Pointer to first child */
|
||||
struct formnode *parent; /* Backpointer to parent */
|
||||
char *nodedata; /* Pointer to the nodes data */
|
||||
unsigned long treesize; /* Size of subtree rooted here */
|
||||
};
|
||||
|
||||
/* A state file descriptor is defined by the following structure. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *filename; /* Full pathname of the state file */
|
||||
FILE *fp; /* Open file pointer for the state file */
|
||||
sf_hdr hdr; /* Copy of the state file-header */
|
||||
char *formtree; /* Pointer to in-memory copy of form-tree */
|
||||
} sfd;
|
||||
|
||||
extern sfd *
|
||||
sfd_fopen PARAMS ((char *, char *));
|
||||
|
||||
extern void
|
||||
sfd_fclose PARAMS ((sfd *));
|
||||
|
||||
extern struct objfile *
|
||||
objfile_from_statefile PARAMS ((sfd *));
|
||||
|
||||
#endif /* !defined (_STATE_H) */
|
Loading…
Reference in a new issue