]> Git Repo - binutils.git/blob - gdb/state.c
*** empty log message ***
[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
202   fnp = (struct formnode *) xmalloc (sizeof (struct formnode));
203   (void) memset (fnp, 0, sizeof (struct formnode));
204   fnp -> sibling = formtree;
205   formtree = fnp;
206   return (fnp);
207 }
208
209 /* Recursively walk a form-tree from the specified node, freeing
210    nodes from the bottom up.  The concept is pretty simple, just free
211    all the child nodes, then all the sibling nodes, then the node
212    itself. */
213
214 static void
215 free_subtree (fnp)
216      struct formnode *fnp;
217 {
218   if (fnp != NULL)
219     {
220       free_subtree (fnp -> child);
221       free_subtree (fnp -> sibling);
222       if (fnp -> nodedata != NULL)
223         {
224           free (fnp -> nodedata);
225         }
226       free (fnp);
227     }
228 }
229
230 /* Recursively walk a form-tree from the specified node, computing the
231    size of each subtree from the bottom up.
232
233    At each node, the file space that will be consumed by the subtree
234    rooted in that node is the sum of all the subtrees rooted in each
235    child node plus the size of the node itself.
236
237    Thus for each node, we size the child subtrees, add to that our
238    size, contribute this size towards the size of any parent node, and
239    then ask any of our siblings to do the same.
240
241    Also, once we know the size of any subtree rooted at this node, we
242    can initialize the offset to the sibling node (if any).
243
244    Since every form-tree node must have valid nodedata at this point,
245    we detect and report a warning for any node that doesn't. */
246
247 static void
248 size_subtree (fnp)
249      struct formnode *fnp;
250 {
251   long *lp;
252
253   if (fnp != NULL)
254     {
255       if (fnp -> nodedata == NULL)
256         {
257           warning ("internal error -- empty form node");
258         }
259       else
260         {
261           size_subtree (fnp -> child);
262           fnp -> treesize += *(long *) fnp -> nodedata;
263           if (fnp -> parent != NULL)
264             {
265               fnp -> parent -> treesize += fnp -> treesize;
266             }
267           if (fnp -> sibling)
268             {
269               size_subtree (fnp -> sibling);
270               lp = (long *) (fnp -> nodedata + 2 * sizeof (long));
271               *lp = fnp -> treesize;
272             }
273         }
274     }
275 }
276
277 /* Recursively walk a form-tree from the specified node, writing
278    nodes from the top down. */
279
280 static void
281 write_subtree (fnp, asfd)
282      struct formnode *fnp;
283      sfd *asfd;
284 {
285   if (fnp != NULL)
286     {
287       if (fnp -> nodedata != NULL)
288         {
289           fwrite (fnp -> nodedata, *(long *) fnp -> nodedata, 1, asfd -> fp);
290         }
291       write_subtree (fnp -> child, asfd);
292       write_subtree (fnp -> sibling, asfd);
293     }
294 }
295
296 /* Free the entire current formtree.  Called via do_cleanups, regardless
297    of whether there is an error or not. */
298
299 static void
300 free_formtree ()
301 {
302   free_subtree (formtree);
303   formtree = NULL;
304 }
305
306 /* Write out the file header.  Generally this is done last, even though
307    it is located at the start of the file, since we need to have file
308    offset to where the annotated form tree was written, and it's size. */
309
310 static void
311 write_header (asfd)
312      sfd *asfd;
313 {
314   fseek (asfd -> fp, 0L, SEEK_SET);
315   fwrite ((char *) &asfd -> hdr, sizeof (asfd -> hdr), 1, asfd -> fp);
316 }
317
318 /* Write out the annotated form tree.  We should already have written out
319    the state data, and noted the file offsets and sizes in each node of
320    the form tree that references part of the state data.
321
322    The form tree can be written anywhere in the file where there is room
323    for it.  Since there is always room at the end of the file, we write
324    it there.  We also need to record the file offset to the start of the
325    form tree, and it's size, for future use when writing the file header.
326
327    In order to compute the sibling references, we need to know, at
328    each node, how much space will be consumed when all of that node's
329    children nodes have been written.  Thus we walk the tree, computing
330    the sizes of the subtrees from the bottom up.  At any node, the
331    offset from the start of that node to the start of the sibling node
332    is simply the size of the node plus the size of the subtree rooted
333    in that node. */
334
335 static void
336 write_formtree (asfd)
337      sfd *asfd;
338 {
339   size_subtree (formtree);
340   fseek (asfd -> fp, 0L, SEEK_END);
341   asfd -> hdr.sf_ftoff = ftell (asfd -> fp);
342   write_subtree (formtree, asfd);
343   asfd -> hdr.sf_ftsize = ftell (asfd -> fp) - asfd -> hdr.sf_ftoff;
344 }
345
346 /* Note that we currently only support having one objfile with dumpable
347    state. */
348
349 static void
350 write_objfile_state (asfd)
351      sfd *asfd;
352 {
353   struct objfile *objfile;
354   struct formnode *fnp;
355   PTR base;
356   PTR breakval;
357   long *lp;
358   unsigned int ftesize;
359   long ftebuf[64];
360   long foffset;
361
362   /* First walk through the objfile list looking for the first objfile
363      that is dumpable. */
364
365   for (objfile = object_files; objfile != NULL; objfile = objfile -> next)
366     {
367       if (objfile -> flags & OBJF_DUMPABLE)
368         {
369           break;
370         }
371     }
372
373   if (objfile == NULL)
374     {
375       warning ("no dumpable objfile was found");
376     }
377   else
378     {
379       fnp = alloc_formnode ();
380       lp = ftebuf;
381
382       lp++;                     /* Skip FTE size slot, filled in at the end. */
383       *lp++ = TAG_objfile;      /* This is an objfile FTE */
384       *lp++ = 0;                /* Zero the sibling reference slot. */
385
386       /* Build an AT_name attribute for the objfile's name, and write
387          the name into the state data. */
388
389       *lp++ = AT_name;
390       *lp++ = (long) ftell (asfd -> fp);
391       fwrite (objfile -> name, strlen (objfile -> name) + 1, 1, asfd -> fp);
392
393       /* Build an AT_addr attribute for the virtual address to which the
394          objfile data is mapped (and needs to be remapped when read in). */
395
396       base = mmap_base ();
397       *lp++ = AT_addr;
398       *lp++ = (long) base;
399
400       /* Build an AT_aux_addr attribute for the address of the objfile
401          structure itself, within the dumpable data.  When we read the objfile
402          back in, we use this address as the pointer the "struct objfile". */
403
404       *lp++ = AT_aux_addr;
405       *lp++ = (long) objfile;
406
407       /* Reposition in state file to next paging boundry so we can mmap the
408          dumpable objfile data when we reload it. */
409
410       foffset = (long) mmap_page_align ((PTR) ftell (asfd -> fp));
411       fseek (asfd -> fp, foffset, SEEK_SET);
412
413       /* Build an AT_offset attribute for the offset in the state file to
414          the start of the dumped objfile data. */
415
416       *lp++ = AT_offset;
417       *lp++ = (long) ftell (asfd -> fp);
418
419       /* Build an AT_size attribute for the size of the dumped objfile data. */
420
421       breakval = mmap_sbrk (0);
422       *lp++ = AT_size;
423       *lp++ = breakval - base;
424
425       /* Write the dumpable data. */ 
426
427       fwrite ((char *) base, breakval - base, 1, asfd -> fp);
428
429       /* Now finish up the FTE by filling in the size slot based on
430          how much of the ftebuf we have used, allocate some memory for
431          it hung off the form tree node, and copy it there. */
432
433       ftebuf[0] = (lp - ftebuf) * sizeof (ftebuf[0]);
434       fnp -> nodedata = (char *) xmalloc (ftebuf[0]);
435       memcpy (fnp -> nodedata, ftebuf, ftebuf[0]);
436     }
437 }
438
439 static void
440 load_state_command (arg_string, from_tty)
441      char *arg_string;
442      int from_tty;
443 {
444   char *filename;
445   char **argv;
446   FILE *fp;
447   struct cleanup *cleanups;
448   
449   dont_repeat ();
450
451   if (arg_string == NULL)
452     {
453       error ("load-state takes a file name and optional state specifiers");
454     }
455   else if ((argv = buildargv (arg_string)) == NULL)
456     {
457       fatal ("virtual memory exhausted.", 0);
458     }
459   cleanups = make_cleanup (freeargv, argv);
460
461   filename = tilde_expand (*argv);
462   make_cleanup (free, filename);
463
464   if ((fp = fopen (filename, "r")) == NULL)
465     {
466       perror_with_name (filename);
467     }
468   make_cleanup (fclose, fp);
469   immediate_quit++;
470
471   while (*++argv != NULL)
472     {
473       if (strcmp (*argv, "symbols") == 0)
474         {
475           if (from_tty
476               && !query ("load symbol table state from file \"%s\"? ",
477                          filename))
478             {
479               error ("Not confirmed.");
480             }
481           load_symbols (fp);
482         }
483       else
484         {
485           error ("unknown state specifier '%s'", *argv);
486         }
487     }
488   immediate_quit--;
489   do_cleanups (cleanups);
490 }
491
492 /* ARGSUSED */
493 static void
494 dump_state_command (arg_string, from_tty)
495      char *arg_string;
496      int from_tty;
497 {
498   char *filename;
499   char **argv;
500   sfd *asfd;
501   struct cleanup *cleanups;
502   
503   dont_repeat ();
504
505   if (arg_string == NULL)
506     {
507       error ("dump-state takes a file name and state specifiers");
508     }
509   else if ((argv = buildargv (arg_string)) == NULL)
510     {
511       fatal ("virtual memory exhausted.", 0);
512     }
513   cleanups = make_cleanup (freeargv, argv);
514
515   filename = tilde_expand (*argv);
516   make_cleanup (free, filename);
517
518   /* Now attempt to create a fresh state file. */
519
520   if ((asfd = sfd_fopen (filename, "w")) == NULL)
521     {
522       perror_with_name (filename);
523     }
524   make_cleanup (sfd_fclose, asfd);
525   make_cleanup (free_formtree, NULL);
526   immediate_quit++;
527
528   /* Now that we have an open and initialized state file, seek to the
529      proper offset to start writing state data and the process the
530      arguments.  For each argument, write the state data and initialize
531      a form-tree node for each piece of state data. */
532
533   fseek (asfd -> fp, sizeof (sf_hdr), SEEK_SET);
534   while (*++argv != NULL)
535     {
536       if (strcmp (*argv, "objfile") == 0)
537         {
538           write_objfile_state (asfd);
539         }
540       else
541         {
542           error ("unknown state specifier '%s'", *argv);
543         }
544
545     }
546
547   /* We have written any state data.  All that is left to do now is
548      write the form-tree and the file header. */
549
550   write_formtree (asfd);
551   write_header (asfd);
552
553   immediate_quit--;
554   do_cleanups (cleanups);
555 }
556
557 static char *
558 find_fte_by_walk (thisfte, endfte, tag)
559      char *thisfte;
560      char *endfte;
561      long tag;
562 {
563   char *found = NULL;
564   char *nextfte;
565   long thistag;
566   long thissize;
567   long siboffset;
568
569   while (thisfte < endfte)
570     {
571       if ((thistag = *(long *)(thisfte + sizeof (long))) == tag)
572         {
573           found = thisfte;
574           break;
575         }
576       else
577         {
578           thissize =  *(long *)(thisfte);
579           siboffset = *(long *)(thisfte + (2 * sizeof (long)));
580           nextfte = thisfte + (siboffset != 0 ? siboffset : thissize);
581           found = find_fte_by_walk (thisfte + thissize, nextfte, tag);
582           thisfte = nextfte;
583         }
584     }
585   return (found);
586 }
587
588 /* Walk the form-tree looking for a specific FTE type.  Returns the first
589    one found that matches the specified tag. */
590
591 static char *
592 find_fte (asfd, tag)
593      sfd *asfd;
594      long tag;
595 {
596   char *ftbase;
597   char *ftend;
598   char *ftep;
599   char *found = NULL;
600
601   if (fseek (asfd -> fp, asfd -> hdr.sf_ftoff, SEEK_SET) == 0)
602     {
603       ftbase = xmalloc (asfd -> hdr.sf_ftsize);
604       ftend = ftbase + asfd -> hdr.sf_ftsize;
605       if (fread (ftbase, asfd -> hdr.sf_ftsize, 1, asfd -> fp) == 1)
606         {
607           ftep = find_fte_by_walk (ftbase, ftend, tag);
608           if (ftep != NULL)
609             {
610               found = xmalloc (*(long *)ftep);
611               memcpy (found, ftep, (int) *(long *)ftep);
612             }
613         }
614       free (ftbase);
615     }
616   return (found);
617 }
618
619 struct objfile *
620 objfile_from_statefile (asfd)
621      sfd *asfd;
622 {
623   struct objfile *objfile = NULL;
624   char *ftep;
625   long *thisattr;
626   long *endattr;
627   PTR base;
628   long foffset;
629   long mapsize;
630
631   ftep = find_fte (asfd, TAG_objfile);
632   thisattr = (long *) (ftep + 3 * sizeof (long));
633   endattr = (long *) (ftep + *(long *)ftep);
634   while (thisattr < endattr)
635     {
636       switch (*thisattr++)
637         {
638           case AT_name:
639             /* Ignore for now */
640             thisattr++;
641             break;
642           case AT_addr:
643             base = (PTR) *thisattr++;
644             break;
645           case AT_aux_addr:
646             objfile = (struct objfile *) *thisattr++;
647             break;
648           case AT_offset:
649             foffset = *thisattr++;
650             break;
651           case AT_size:
652             mapsize = *thisattr++;
653             break;
654         }
655     }
656   if (mmap_remap (base, mapsize, (int) fileno (asfd -> fp), foffset) != base)
657     {
658       print_sys_errmsg (asfd -> filename, errno);
659       error ("mapping failed");
660     }
661
662   return (objfile);
663 }
664
665 #else
666
667 struct objfile *
668 objfile_from_statefile (asfd)
669      sfd *asfd;
670 {
671   error ("this version of gdb doesn't support reloading symtabs from state files");
672 }
673
674 #endif  /* HAVE_MMAP */
675
676 /* Close a state file, freeing all memory that was used by the state
677    file descriptor, closing the raw file pointer, etc. */
678
679 void
680 sfd_fclose (asfd)
681      sfd *asfd;
682 {
683   if (asfd != NULL)
684     {
685       if (asfd -> fp != NULL)
686         {
687           fclose (asfd -> fp);
688         }
689       if (asfd -> filename != NULL)
690         {
691           free (asfd -> filename);
692         }
693       free (asfd);
694     }
695 }
696
697 /* Given the name of a possible statefile, and flags to use to open it,
698    try to open the file and prepare it for use.
699
700    If the flags contain 'r', then we want to read an existing state
701    file, so attempt to read in the state file header and determine if this
702    is a valid state file.  If not, return NULL.
703
704    Returns a pointer to a properly initialized state file descriptor if
705    successful. */
706
707 sfd *
708 sfd_fopen (name, flags)
709      char *name;
710      char *flags;
711 {
712   int success = 0;
713   sfd *asfd;
714
715   asfd = (sfd *) xmalloc (sizeof (sfd));
716   (void) memset (asfd, 0, sizeof (sfd));
717   asfd -> filename = xmalloc (strlen (name) + 1);
718   (void) strcpy (asfd -> filename, name);
719
720   if ((asfd -> fp = fopen (asfd -> filename, flags)) != NULL)
721     {
722       /* We have the file, now see if we are reading an existing file
723          or writing to a new file.  We don't currently support "rw". */
724       if (strchr (flags, 'r') != NULL)
725         {
726           if (fread ((char *) &asfd -> hdr, sizeof (asfd -> hdr), 1,
727                      asfd -> fp) == 1)
728             {
729               if (SF_GOOD_MAGIC (asfd))
730                 {
731                   success = 1;
732                 }
733             }
734         }
735       else
736         {
737           /* This is a new state file.  Initialize various things. */
738           asfd -> hdr.sf_mag0 = SF_MAG0;
739           asfd -> hdr.sf_mag1 = SF_MAG1;
740           asfd -> hdr.sf_mag2 = SF_MAG2;
741           asfd -> hdr.sf_mag3 = SF_MAG3;
742           success = 1;
743         }
744     }
745
746   if (!success)
747     {
748       sfd_fclose (asfd);
749       asfd = NULL;
750     }
751   return (asfd);
752   
753 }
754
755 \f
756 void
757 _initialize_state ()
758 {
759
760 #ifdef HAVE_MMAP
761
762   add_com ("load-state", class_support, load_state_command,
763    "Load some saved gdb state from FILE.\n\
764 Select and load some portion of gdb's saved state from the specified file.\n\
765 The dump-state command may be used to save various portions of gdb's\n\
766 internal state.");
767
768   add_com ("dump-state", class_support, dump_state_command,
769    "Dump some of gdb's state to FILE.\n\
770 Select and dump some portion of gdb's internal state to the specified file.\n\
771 The load-state command may be used to reload various portions of gdb's\n\
772 internal state from the file.");
773
774 #endif  /* HAVE_MMAP */
775
776 }
This page took 0.070273 seconds and 4 git commands to generate.