]> Git Repo - binutils.git/blob - gdb/state.c
* nlm/gdbserve.c: conditionalize header file inclusion for either
[binutils.git] / gdb / state.c
1 /* Support for dumping and reloading various pieces of GDB's internal state.
2    Copyright 1992 Free Software Foundation, Inc.
3    Contributed by Cygnus Support, using pieces from other GDB modules.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /* This file provides support for dumping and then later reloading various
22    portions of gdb's internal state.  It was originally implemented to
23    support a need for mapping in an image of gdb's symbol table from an
24    external file, where this image was created by an external program, such
25    as an incremental linker.  However, it was generalized to enable future
26    support for dumping and reloading various other useful pieces of gdb's
27    internal state.
28
29    State files have a fairly simple form which is intended to be easily
30    extensible.  The basic format is:
31
32         <file-header> <state-data> <form-tree>
33
34    Where:
35
36         file-header     A simple file-header containing a magic number
37                         so that gdb (and other readers) can quickly
38                         determine what kind of file this is, and a file
39                         offset to the root of the form-tree.
40
41         state-data      The "raw" state-data that is referenced by nodes
42                         in the form-tree.
43
44         form-tree       A tree of arbitrarily sized nodes containing
45                         information about gdb's internal state, and
46                         possibly referencing data in the state-data section
47                         of the file.  Resembles DWARF in some respects.
48
49    When writing a state file, a hole is left for the file-header at the
50    beginning of the file, the state data is written immediately after the
51    file header (while storing the file offsets and sizes back into the
52    internal form-tree along the way), the form-tree itself is written
53    at the end of the file, and then the file header is written by seeking
54    back to the beginning of the file.  This order is required because
55    the form tree contains file offsets and sizes in the state data portion
56    of the file, and the file header contains the file offset to the start
57    of the form tree.
58
59    Readers simply open the file, validate the magic number, seek to the
60    root of the form-tree, and walk the tree looking for the information that
61    they are interested in (and ignoring things that they aren't, or don't
62    understand).
63
64    */
65
66
67 #include "defs.h"
68 #include "symtab.h"
69 #include "bfd.h"
70 #include "symfile.h"
71 #include "state.h"
72
73 #ifndef SEEK_SET
74 #define SEEK_SET 0
75 #endif
76
77 #ifndef SEEK_END
78 #define SEEK_END 2
79 #endif
80
81 /* Inside the state file, the form-tree consists of a series of
82    form-tree entries (FTE's).  The parent/child/sibling relationships
83    are implied by the ordering and by an explicit sibling reference
84    in FTE's that have siblings.
85
86    Specifically, given two sequential FTE's, say A and B, if B immediately
87    follows A, and A does not have a sibling reference to B, then B is
88    the first child of A.  Otherwise B must be a sibling of A and A must
89    have a sibling reference for it.
90
91    Each FTE is simply an array of long integers, with at least three
92    members.  This form was chosen over a packed data form for simplicity
93    in access, not having to worry about the relative sizes of the different
94    integers (short, int, long), and not having to worry about alignment
95    constraints.  Also in the name of simplicity, every FTE has a sibling
96    reference slot reserved for it, even if there are no siblings.
97
98    The first value in an FTE is the size of the FTE in bytes, including
99    the size value itself.  The second entry contains a tag which indicates
100    the type of the FTE.  The third entry is a sibling reference, which either
101    refers to a valid sibling node or is zero.  Following is zero or more
102    attributes, each of which consists of one or more long values. */
103
104 /* Tag names and codes. */
105
106 #define TAG_padding     0x0000          /* Padding */
107 #define TAG_objfile     0x0001          /* Dumped objfile */
108
109 /* Form names, codes, and macros. */
110
111 #define FORM_ABSREF     0x01            /* Next long is absolute file offset */
112 #define FORM_RELREF     0x02            /* Next long is relative file offset */
113 #define FORM_IVAL       0x03            /* Next long is int value */
114 #define FORM_ADDR       0x04            /* Next long is mem addr */
115
116 #define FORM_MASK       0xFF
117 #define FORM_X(atr)     ((atr) & FORM_MASK)
118
119 /* Attribute names and codes. */
120
121 #define AT_sibling      (0x0100 | FORM_RELREF)  /* Reference to sibling node */
122 #define AT_name         (0x0200 | FORM_ABSREF)  /* Reference to a string */
123 #define AT_offset       (0x0300 | FORM_ABSREF)  /* Reference to generic data */
124 #define AT_size         (0x0400 | FORM_IVAL)
125 #define AT_addr         (0x0500 | FORM_ADDR)
126 #define AT_aux_addr     (0x0600 | FORM_ADDR)
127
128 /* */
129
130 static void
131 load_symbols PARAMS ((FILE *));
132
133 static void
134 dump_state_command PARAMS ((char *, int));
135
136 static void
137 load_state_command PARAMS ((char *, int));
138
139 #ifdef HAVE_MMAP
140
141 static void
142 write_header PARAMS ((sfd *));
143
144 static void
145 write_formtree PARAMS ((sfd *));
146
147 static void
148 write_objfile_state PARAMS ((sfd *));
149
150 static void
151 free_subtree PARAMS ((struct formnode *));
152
153 static void
154 size_subtree PARAMS ((struct formnode *));
155
156 #endif
157
158 struct formnode *formtree = NULL;
159
160 /* ARGSUSED */
161 static void
162 load_symbols (statefile)
163      FILE *statefile;
164 {
165
166 #if 0
167   /* Discard old symbols.  FIXME: This is essentially symbol_file_command's
168      body when there is no name.  Make it a common function that is
169      called from each place. */
170
171   if (symfile_objfile)
172     {
173       free_objfile (symfile_objfile);
174     }
175   symfile_objfile = NULL;
176 #endif
177
178 #if 0 && defined (HAVE_MMAP)
179   if (mtop > mbase)
180     {
181       warning ("internal error: mbase (%08x) != mtop (%08x)",
182                mbase, mtop);
183       munmap (mbase, mtop - mbase);
184     }
185 #endif  /* HAVE_MMAP */
186
187   /* Getting new symbols may change our opinion about what is frameless. */
188
189   reinit_frame_cache ();
190
191 }
192
193 #ifdef HAVE_MMAP
194
195 /* Allocate a form node */
196
197 static struct formnode *
198 alloc_formnode ()
199 {
200   struct formnode *fnp;
201   fnp = (struct formnode *) xmalloc (sizeof (struct formnode));
202   (void) memset (fnp, 0, sizeof (struct formnode));
203   fnp -> sibling = formtree;
204   formtree = fnp;
205   return (fnp);
206 }
207
208 /* Recursively walk a form-tree from the specified node, freeing
209    nodes from the bottom up.  The concept is pretty simple, just free
210    all the child nodes, then all the sibling nodes, then the node
211    itself. */
212
213 static void
214 free_subtree (fnp)
215      struct formnode *fnp;
216 {
217   if (fnp != NULL)
218     {
219       free_subtree (fnp -> child);
220       free_subtree (fnp -> sibling);
221       if (fnp -> nodedata != NULL)
222         {
223           free (fnp -> nodedata);
224         }
225       free (fnp);
226     }
227 }
228
229 /* Recursively walk a form-tree from the specified node, computing the
230    size of each subtree from the bottom up.
231
232    At each node, the file space that will be consumed by the subtree
233    rooted in that node is the sum of all the subtrees rooted in each
234    child node plus the size of the node itself.
235
236    Thus for each node, we size the child subtrees, add to that our
237    size, contribute this size towards the size of any parent node, and
238    then ask any of our siblings to do the same.
239
240    Also, once we know the size of any subtree rooted at this node, we
241    can initialize the offset to the sibling node (if any).
242
243    Since every form-tree node must have valid nodedata at this point,
244    we detect and report a warning for any node that doesn't. */
245
246 static void
247 size_subtree (fnp)
248      struct formnode *fnp;
249 {
250   long *lp;
251
252   if (fnp != NULL)
253     {
254       if (fnp -> nodedata == NULL)
255         {
256           warning ("internal error -- empty form node");
257         }
258       else
259         {
260           size_subtree (fnp -> child);
261           fnp -> treesize += *(long *) fnp -> nodedata;
262           if (fnp -> parent != NULL)
263             {
264               fnp -> parent -> treesize += fnp -> treesize;
265             }
266           if (fnp -> sibling)
267             {
268               size_subtree (fnp -> sibling);
269               lp = (long *) (fnp -> nodedata + 2 * sizeof (long));
270               *lp = fnp -> treesize;
271             }
272         }
273     }
274 }
275
276 /* Recursively walk a form-tree from the specified node, writing
277    nodes from the top down. */
278
279 static void
280 write_subtree (fnp, asfd)
281      struct formnode *fnp;
282      sfd *asfd;
283 {
284   if (fnp != NULL)
285     {
286       if (fnp -> nodedata != NULL)
287         {
288           fwrite (fnp -> nodedata, *(long *) fnp -> nodedata, 1, asfd -> fp);
289         }
290       write_subtree (fnp -> child, asfd);
291       write_subtree (fnp -> sibling, asfd);
292     }
293 }
294
295 /* Free the entire current formtree.  Called via do_cleanups, regardless
296    of whether there is an error or not. */
297
298 static void
299 free_formtree ()
300 {
301   free_subtree (formtree);
302   formtree = NULL;
303 }
304
305 /* Write out the file header.  Generally this is done last, even though
306    it is located at the start of the file, since we need to have file
307    offset to where the annotated form tree was written, and it's size. */
308
309 static void
310 write_header (asfd)
311      sfd *asfd;
312 {
313   fseek (asfd -> fp, 0L, SEEK_SET);
314   fwrite ((char *) &asfd -> hdr, sizeof (asfd -> hdr), 1, asfd -> fp);
315 }
316
317 /* Write out the annotated form tree.  We should already have written out
318    the state data, and noted the file offsets and sizes in each node of
319    the form tree that references part of the state data.
320
321    The form tree can be written anywhere in the file where there is room
322    for it.  Since there is always room at the end of the file, we write
323    it there.  We also need to record the file offset to the start of the
324    form tree, and it's size, for future use when writing the file header.
325
326    In order to compute the sibling references, we need to know, at
327    each node, how much space will be consumed when all of that node's
328    children nodes have been written.  Thus we walk the tree, computing
329    the sizes of the subtrees from the bottom up.  At any node, the
330    offset from the start of that node to the start of the sibling node
331    is simply the size of the node plus the size of the subtree rooted
332    in that node. */
333
334 static void
335 write_formtree (asfd)
336      sfd *asfd;
337 {
338   size_subtree (formtree);
339   fseek (asfd -> fp, 0L, SEEK_END);
340   asfd -> hdr.sf_ftoff = ftell (asfd -> fp);
341   write_subtree (formtree, asfd);
342   asfd -> hdr.sf_ftsize = ftell (asfd -> fp) - asfd -> hdr.sf_ftoff;
343 }
344
345 /* Note that we currently only support having one objfile with dumpable
346    state. */
347
348 static void
349 write_objfile_state (asfd)
350      sfd *asfd;
351 {
352   struct objfile *objfile;
353   struct formnode *fnp;
354   PTR base;
355   PTR breakval;
356   long *lp;
357   unsigned int ftesize;
358   long ftebuf[64];
359   long foffset;
360
361   /* First walk through the objfile list looking for the first objfile
362      that is dumpable. */
363
364   for (objfile = object_files; objfile != NULL; objfile = objfile -> next)
365     {
366       if (objfile -> flags & OBJF_DUMPABLE)
367         {
368           break;
369         }
370     }
371
372   if (objfile == NULL)
373     {
374       warning ("no dumpable objfile was found");
375     }
376   else
377     {
378       fnp = alloc_formnode ();
379       lp = ftebuf;
380
381       lp++;                     /* Skip FTE size slot, filled in at the end. */
382       *lp++ = TAG_objfile;      /* This is an objfile FTE */
383       *lp++ = 0;                /* Zero the sibling reference slot. */
384
385       /* Build an AT_name attribute for the objfile's name, and write
386          the name into the state data. */
387
388       *lp++ = AT_name;
389       *lp++ = (long) ftell (asfd -> fp);
390       fwrite (objfile -> name, strlen (objfile -> name) + 1, 1, asfd -> fp);
391
392       /* Build an AT_addr attribute for the virtual address to which the
393          objfile data is mapped (and needs to be remapped when read in). */
394
395       base = mmap_base ();
396       *lp++ = AT_addr;
397       *lp++ = (long) base;
398
399       /* Build an AT_aux_addr attribute for the address of the objfile
400          structure itself, within the dumpable data.  When we read the objfile
401          back in, we use this address as the pointer the "struct objfile". */
402
403       *lp++ = AT_aux_addr;
404       *lp++ = (long) objfile;
405
406       /* Reposition in state file to next paging boundry so we can mmap the
407          dumpable objfile data when we reload it. */
408
409       foffset = (long) mmap_page_align ((PTR) ftell (asfd -> fp));
410       fseek (asfd -> fp, foffset, SEEK_SET);
411
412       /* Build an AT_offset attribute for the offset in the state file to
413          the start of the dumped objfile data. */
414
415       *lp++ = AT_offset;
416       *lp++ = (long) ftell (asfd -> fp);
417
418       /* Build an AT_size attribute for the size of the dumped objfile data. */
419
420       breakval = mmap_sbrk (0);
421       *lp++ = AT_size;
422       *lp++ = breakval - base;
423
424       /* Write the dumpable data. */ 
425
426       fwrite ((char *) base, breakval - base, 1, asfd -> fp);
427
428       /* Now finish up the FTE by filling in the size slot based on
429          how much of the ftebuf we have used, allocate some memory for
430          it hung off the form tree node, and copy it there. */
431
432       ftebuf[0] = (lp - ftebuf) * sizeof (ftebuf[0]);
433       fnp -> nodedata = (char *) xmalloc (ftebuf[0]);
434       memcpy (fnp -> nodedata, ftebuf, ftebuf[0]);
435     }
436 }
437
438 static void
439 load_state_command (arg_string, from_tty)
440      char *arg_string;
441      int from_tty;
442 {
443   char *filename;
444   char **argv;
445   FILE *fp;
446   struct cleanup *cleanups;
447   
448   dont_repeat ();
449
450   if (arg_string == NULL)
451     {
452       error ("load-state takes a file name and optional state specifiers");
453     }
454   else if ((argv = buildargv (arg_string)) == NULL)
455     {
456       fatal ("virtual memory exhausted.", 0);
457     }
458   cleanups = make_cleanup (freeargv, argv);
459
460   filename = tilde_expand (*argv);
461   make_cleanup (free, filename);
462
463   if ((fp = fopen (filename, FOPEN_RB)) == NULL)
464     {
465       perror_with_name (filename);
466     }
467   make_cleanup (fclose, fp);
468   immediate_quit++;
469
470   while (*++argv != NULL)
471     {
472       if (STREQ (*argv, "symbols"))
473         {
474           if (from_tty
475               && !query ("load symbol table state from file \"%s\"? ",
476                          filename))
477             {
478               error ("Not confirmed.");
479             }
480           load_symbols (fp);
481         }
482       else
483         {
484           error ("unknown state specifier '%s'", *argv);
485         }
486     }
487   immediate_quit--;
488   do_cleanups (cleanups);
489 }
490
491 /* ARGSUSED */
492 static void
493 dump_state_command (arg_string, from_tty)
494      char *arg_string;
495      int from_tty;
496 {
497   char *filename;
498   char **argv;
499   sfd *asfd;
500   struct cleanup *cleanups;
501   
502   dont_repeat ();
503
504   if (arg_string == NULL)
505     {
506       error ("dump-state takes a file name and state specifiers");
507     }
508   else if ((argv = buildargv (arg_string)) == NULL)
509     {
510       fatal ("virtual memory exhausted.", 0);
511     }
512   cleanups = make_cleanup (freeargv, argv);
513
514   filename = tilde_expand (*argv);
515   make_cleanup (free, filename);
516
517   /* Now attempt to create a fresh state file. */
518
519   if ((asfd = sfd_fopen (filename, FOPEN_WB)) == NULL)
520     {
521       perror_with_name (filename);
522     }
523   make_cleanup (sfd_fclose, asfd);
524   make_cleanup (free_formtree, NULL);
525   immediate_quit++;
526
527   /* Now that we have an open and initialized state file, seek to the
528      proper offset to start writing state data and the process the
529      arguments.  For each argument, write the state data and initialize
530      a form-tree node for each piece of state data. */
531
532   fseek (asfd -> fp, sizeof (sf_hdr), SEEK_SET);
533   while (*++argv != NULL)
534     {
535       if (STREQ (*argv, "objfile"))
536         {
537           write_objfile_state (asfd);
538         }
539       else
540         {
541           error ("unknown state specifier '%s'", *argv);
542         }
543
544     }
545
546   /* We have written any state data.  All that is left to do now is
547      write the form-tree and the file header. */
548
549   write_formtree (asfd);
550   write_header (asfd);
551
552   immediate_quit--;
553   do_cleanups (cleanups);
554 }
555
556 static char *
557 find_fte_by_walk (thisfte, endfte, tag)
558      char *thisfte;
559      char *endfte;
560      long tag;
561 {
562   char *found = NULL;
563   char *nextfte;
564   long thistag;
565   long thissize;
566   long siboffset;
567
568   while (thisfte < endfte)
569     {
570       if ((thistag = *(long *)(thisfte + sizeof (long))) == tag)
571         {
572           found = thisfte;
573           break;
574         }
575       else
576         {
577           thissize =  *(long *)(thisfte);
578           siboffset = *(long *)(thisfte + (2 * sizeof (long)));
579           nextfte = thisfte + (siboffset != 0 ? siboffset : thissize);
580           found = find_fte_by_walk (thisfte + thissize, nextfte, tag);
581           thisfte = nextfte;
582         }
583     }
584   return (found);
585 }
586
587 /* Walk the form-tree looking for a specific FTE type.  Returns the first
588    one found that matches the specified tag. */
589
590 static char *
591 find_fte (asfd, tag)
592      sfd *asfd;
593      long tag;
594 {
595   char *ftbase;
596   char *ftend;
597   char *ftep;
598   char *found = NULL;
599
600   if (fseek (asfd -> fp, asfd -> hdr.sf_ftoff, SEEK_SET) == 0)
601     {
602       ftbase = xmalloc (asfd -> hdr.sf_ftsize);
603       ftend = ftbase + asfd -> hdr.sf_ftsize;
604       if (fread (ftbase, asfd -> hdr.sf_ftsize, 1, asfd -> fp) == 1)
605         {
606           ftep = find_fte_by_walk (ftbase, ftend, tag);
607           if (ftep != NULL)
608             {
609               found = xmalloc (*(long *)ftep);
610               memcpy (found, ftep, (int) *(long *)ftep);
611             }
612         }
613       free (ftbase);
614     }
615   return (found);
616 }
617
618 struct objfile *
619 objfile_from_statefile (asfd)
620      sfd *asfd;
621 {
622   struct objfile *objfile = NULL;
623   char *ftep;
624   long *thisattr;
625   long *endattr;
626   PTR base;
627   long foffset;
628   long mapsize;
629
630   ftep = find_fte (asfd, TAG_objfile);
631   thisattr = (long *) (ftep + 3 * sizeof (long));
632   endattr = (long *) (ftep + *(long *)ftep);
633   while (thisattr < endattr)
634     {
635       switch (*thisattr++)
636         {
637           case AT_name:
638             /* Ignore for now */
639             thisattr++;
640             break;
641           case AT_addr:
642             base = (PTR) *thisattr++;
643             break;
644           case AT_aux_addr:
645             objfile = (struct objfile *) *thisattr++;
646             break;
647           case AT_offset:
648             foffset = *thisattr++;
649             break;
650           case AT_size:
651             mapsize = *thisattr++;
652             break;
653         }
654     }
655   if (mmap_remap (base, mapsize, (int) fileno (asfd -> fp), foffset) != base)
656     {
657       print_sys_errmsg (asfd -> filename, errno);
658       error ("mapping failed");
659     }
660
661   return (objfile);
662 }
663
664 #else
665
666 struct objfile *
667 objfile_from_statefile (asfd)
668      sfd *asfd;
669 {
670   error ("this version of gdb doesn't support reloading symtabs from state files");
671 }
672
673 #endif  /* HAVE_MMAP */
674
675 /* Close a state file, freeing all memory that was used by the state
676    file descriptor, closing the raw file pointer, etc. */
677
678 void
679 sfd_fclose (asfd)
680      sfd *asfd;
681 {
682   if (asfd != NULL)
683     {
684       if (asfd -> fp != NULL)
685         {
686           fclose (asfd -> fp);
687         }
688       if (asfd -> filename != NULL)
689         {
690           free (asfd -> filename);
691         }
692       free (asfd);
693     }
694 }
695
696 /* Given the name of a possible statefile, and flags to use to open it,
697    try to open the file and prepare it for use.
698
699    If the flags contain 'r', then we want to read an existing state
700    file, so attempt to read in the state file header and determine if this
701    is a valid state file.  If not, return NULL.
702
703    Returns a pointer to a properly initialized state file descriptor if
704    successful. */
705
706 sfd *
707 sfd_fopen (name, flags)
708      char *name;
709      char *flags;
710 {
711   int success = 0;
712   sfd *asfd;
713
714   asfd = (sfd *) xmalloc (sizeof (sfd));
715   (void) memset (asfd, 0, sizeof (sfd));
716   asfd -> filename = xmalloc (strlen (name) + 1);
717   (void) strcpy (asfd -> filename, name);
718
719   if ((asfd -> fp = fopen (asfd -> filename, flags)) != NULL)
720     {
721       /* We have the file, now see if we are reading an existing file
722          or writing to a new file.  We don't currently support "rw". */
723       if (strchr (flags, 'r') != NULL)
724         {
725           if (fread ((char *) &asfd -> hdr, sizeof (asfd -> hdr), 1,
726                      asfd -> fp) == 1)
727             {
728               if (SF_GOOD_MAGIC (asfd))
729                 {
730                   success = 1;
731                 }
732             }
733         }
734       else
735         {
736           /* This is a new state file.  Initialize various things. */
737           asfd -> hdr.sf_mag0 = SF_MAG0;
738           asfd -> hdr.sf_mag1 = SF_MAG1;
739           asfd -> hdr.sf_mag2 = SF_MAG2;
740           asfd -> hdr.sf_mag3 = SF_MAG3;
741           success = 1;
742         }
743     }
744
745   if (!success)
746     {
747       sfd_fclose (asfd);
748       asfd = NULL;
749     }
750   return (asfd);
751   
752 }
753
754 \f
755 void
756 _initialize_state ()
757 {
758
759 #ifdef HAVE_MMAP
760
761   add_com ("load-state", class_support, load_state_command,
762    "Load some saved gdb state from FILE.\n\
763 Select and load some portion of gdb's saved state from the specified file.\n\
764 The dump-state command may be used to save various portions of gdb's\n\
765 internal state.");
766
767   add_com ("dump-state", class_support, dump_state_command,
768    "Dump some of gdb's state to FILE.\n\
769 Select and dump some portion of gdb's internal state to the specified file.\n\
770 The load-state command may be used to reload various portions of gdb's\n\
771 internal state from the file.");
772
773 #endif  /* HAVE_MMAP */
774
775 }
This page took 0.068491 seconds and 4 git commands to generate.