7b4ac7e1 |
1 | /* Do various things to symbol tables (other than lookup)), for GDB. |
4187119d |
2 | Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc. |
7b4ac7e1 |
3 | |
4187119d |
4 | This file is part of GDB. |
7b4ac7e1 |
5 | |
4187119d |
6 | GDB is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 1, or (at your option) |
9 | any later version. |
7b4ac7e1 |
10 | |
4187119d |
11 | GDB is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GDB; see the file COPYING. If not, write to |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
7b4ac7e1 |
19 | |
20 | |
21 | #include "defs.h" |
7b4ac7e1 |
22 | #include "symtab.h" |
23 | |
24 | #include <stdio.h> |
25 | #include <obstack.h> |
26 | |
27 | static void free_symtab (); |
28 | |
7b4ac7e1 |
29 | \f |
30 | /* Free all the symtabs that are currently installed, |
31 | and all storage associated with them. |
32 | Leaves us in a consistent state with no symtabs installed. */ |
33 | |
34 | void |
35 | free_all_symtabs () |
36 | { |
37 | register struct symtab *s, *snext; |
38 | |
39 | /* All values will be invalid because their types will be! */ |
40 | |
41 | clear_value_history (); |
42 | clear_displays (); |
43 | clear_internalvars (); |
44 | clear_breakpoints (); |
45 | set_default_breakpoint (0, 0, 0, 0); |
46 | |
47 | current_source_symtab = 0; |
48 | |
49 | for (s = symtab_list; s; s = snext) |
50 | { |
51 | snext = s->next; |
52 | free_symtab (s); |
53 | } |
54 | symtab_list = 0; |
55 | obstack_free (symbol_obstack, 0); |
56 | obstack_init (symbol_obstack); |
57 | |
58 | if (misc_function_vector) |
59 | free (misc_function_vector); |
60 | misc_function_count = 0; |
61 | misc_function_vector = 0; |
62 | } |
63 | |
64 | /* Free a struct block <- B and all the symbols defined in that block. */ |
65 | |
66 | static void |
67 | free_symtab_block (b) |
68 | struct block *b; |
69 | { |
70 | register int i, n; |
71 | n = BLOCK_NSYMS (b); |
72 | for (i = 0; i < n; i++) |
73 | { |
74 | free (SYMBOL_NAME (BLOCK_SYM (b, i))); |
75 | free (BLOCK_SYM (b, i)); |
76 | } |
77 | free (b); |
78 | } |
79 | |
80 | /* Free all the storage associated with the struct symtab <- S. |
81 | Note that some symtabs have contents malloc'ed structure by structure, |
82 | while some have contents that all live inside one big block of memory, |
83 | and some share the contents of another symbol table and so you should |
84 | not free the contents on their behalf (except sometimes the linetable, |
85 | which maybe per symtab even when the rest is not). |
86 | It is s->free_code that says which alternative to use. */ |
87 | |
88 | static void |
89 | free_symtab (s) |
90 | register struct symtab *s; |
91 | { |
92 | register int i, n; |
93 | register struct blockvector *bv; |
94 | register struct type *type; |
95 | register struct typevector *tv; |
96 | |
97 | switch (s->free_code) |
98 | { |
99 | case free_nothing: |
100 | /* All the contents are part of a big block of memory |
101 | and some other symtab is in charge of freeing that block. |
102 | Therefore, do nothing. */ |
103 | break; |
104 | |
7b4ac7e1 |
105 | case free_contents: |
106 | /* Here all the contents were malloc'ed structure by structure |
107 | and must be freed that way. */ |
108 | /* First free the blocks (and their symbols. */ |
109 | bv = BLOCKVECTOR (s); |
110 | n = BLOCKVECTOR_NBLOCKS (bv); |
111 | for (i = 0; i < n; i++) |
112 | free_symtab_block (BLOCKVECTOR_BLOCK (bv, i)); |
113 | /* Free the blockvector itself. */ |
114 | free (bv); |
115 | /* Free the type vector. */ |
116 | tv = TYPEVECTOR (s); |
632ea0cc |
117 | free (tv); |
7b4ac7e1 |
118 | /* Also free the linetable. */ |
119 | |
120 | case free_linetable: |
121 | /* Everything will be freed either by our `free_ptr' |
122 | or by some other symbatb, except for our linetable. |
123 | Free that now. */ |
124 | free (LINETABLE (s)); |
125 | break; |
126 | } |
127 | |
128 | /* If there is a single block of memory to free, free it. */ |
129 | if (s->free_ptr) |
130 | free (s->free_ptr); |
131 | |
132 | if (s->line_charpos) |
133 | free (s->line_charpos); |
134 | free (s->filename); |
135 | free (s); |
136 | } |
137 | \f |
138 | /* Convert a raw symbol-segment to a struct symtab, |
139 | and relocate its internal pointers so that it is valid. */ |
140 | |
141 | /* This is how to relocate one pointer, given a name for it. |
142 | Works independent of the type of object pointed to. */ |
143 | #define RELOCATE(slot) (slot ? (* (char **) &slot += relocation) : 0) |
144 | |
145 | /* This is the inverse of RELOCATE. We use it when storing |
146 | a core address into a slot that has yet to be relocated. */ |
147 | #define UNRELOCATE(slot) (slot ? (* (char **) &slot -= relocation) : 0) |
148 | |
149 | /* During the process of relocation, this holds the amount to relocate by |
150 | (the address of the file's symtab data, in core in the debugger). */ |
151 | static int relocation; |
152 | |
153 | #define CORE_RELOCATE(slot) \ |
154 | ((slot) += (((slot) < data_start) ? text_relocation \ |
155 | : ((slot) < bss_start) ? data_relocation : bss_relocation)) |
156 | |
157 | #define TEXT_RELOCATE(slot) ((slot) += text_relocation) |
158 | |
159 | /* Relocation amounts for addresses in the program's core image. */ |
160 | static int text_relocation, data_relocation, bss_relocation; |
161 | |
162 | /* Boundaries that divide program core addresses into text, data and bss; |
163 | used to determine which relocation amount to use. */ |
164 | static int data_start, bss_start; |
165 | |
166 | static void relocate_typevector (); |
167 | static void relocate_blockvector (); |
168 | static void relocate_type (); |
169 | static void relocate_block (); |
170 | static void relocate_symbol (); |
632ea0cc |
171 | static void relocate_source (); |
7b4ac7e1 |
172 | |
632ea0cc |
173 | /* Relocate a file's symseg so that all the pointers are valid C pointers. |
174 | Value is a `struct symtab'; but it is not suitable for direct |
175 | insertion into the `symtab_list' because it describes several files. */ |
7b4ac7e1 |
176 | |
177 | static struct symtab * |
178 | relocate_symtab (root) |
179 | struct symbol_root *root; |
180 | { |
181 | struct symtab *sp = (struct symtab *) xmalloc (sizeof (struct symtab)); |
182 | bzero (sp, sizeof (struct symtab)); |
183 | |
184 | relocation = (int) root; |
185 | text_relocation = root->textrel; |
186 | data_relocation = root->datarel; |
187 | bss_relocation = root->bssrel; |
188 | data_start = root->databeg; |
189 | bss_start = root->bssbeg; |
190 | |
191 | sp->filename = root->filename; |
192 | sp->ldsymoff = root->ldsymoff; |
193 | sp->language = root->language; |
194 | sp->compilation = root->compilation; |
195 | sp->version = root->version; |
196 | sp->blockvector = root->blockvector; |
197 | sp->typevector = root->typevector; |
7b4ac7e1 |
198 | |
199 | RELOCATE (TYPEVECTOR (sp)); |
200 | RELOCATE (BLOCKVECTOR (sp)); |
201 | RELOCATE (sp->version); |
202 | RELOCATE (sp->compilation); |
203 | RELOCATE (sp->filename); |
204 | |
205 | relocate_typevector (TYPEVECTOR (sp)); |
206 | relocate_blockvector (BLOCKVECTOR (sp)); |
207 | |
208 | return sp; |
209 | } |
210 | |
7b4ac7e1 |
211 | static void |
212 | relocate_blockvector (blp) |
213 | register struct blockvector *blp; |
214 | { |
215 | register int nblocks = BLOCKVECTOR_NBLOCKS (blp); |
216 | register int i; |
217 | for (i = 0; i < nblocks; i++) |
218 | RELOCATE (BLOCKVECTOR_BLOCK (blp, i)); |
219 | for (i = 0; i < nblocks; i++) |
220 | relocate_block (BLOCKVECTOR_BLOCK (blp, i)); |
221 | } |
222 | |
223 | static void |
224 | relocate_block (bp) |
225 | register struct block *bp; |
226 | { |
227 | register int nsyms = BLOCK_NSYMS (bp); |
228 | register int i; |
229 | |
230 | TEXT_RELOCATE (BLOCK_START (bp)); |
231 | TEXT_RELOCATE (BLOCK_END (bp)); |
232 | |
233 | /* These two should not be recursively processed. |
234 | The superblock need not be because all blocks are |
235 | processed from relocate_blockvector. |
236 | The function need not be because it will be processed |
237 | under the block which is its scope. */ |
238 | RELOCATE (BLOCK_SUPERBLOCK (bp)); |
239 | RELOCATE (BLOCK_FUNCTION (bp)); |
240 | |
241 | for (i = 0; i < nsyms; i++) |
242 | RELOCATE (BLOCK_SYM (bp, i)); |
243 | |
244 | for (i = 0; i < nsyms; i++) |
245 | relocate_symbol (BLOCK_SYM (bp, i)); |
246 | } |
247 | |
248 | static void |
249 | relocate_symbol (sp) |
250 | register struct symbol *sp; |
251 | { |
252 | RELOCATE (SYMBOL_NAME (sp)); |
253 | if (SYMBOL_CLASS (sp) == LOC_BLOCK) |
254 | { |
255 | RELOCATE (SYMBOL_BLOCK_VALUE (sp)); |
256 | /* We can assume the block that belongs to this symbol |
257 | is not relocated yet, since it comes after |
258 | the block that contains this symbol. */ |
259 | BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp)) = sp; |
260 | UNRELOCATE (BLOCK_FUNCTION (SYMBOL_BLOCK_VALUE (sp))); |
261 | } |
262 | else if (SYMBOL_CLASS (sp) == LOC_STATIC) |
263 | CORE_RELOCATE (SYMBOL_VALUE (sp)); |
264 | else if (SYMBOL_CLASS (sp) == LOC_LABEL) |
265 | TEXT_RELOCATE (SYMBOL_VALUE (sp)); |
266 | RELOCATE (SYMBOL_TYPE (sp)); |
267 | } |
268 | |
632ea0cc |
269 | static void |
270 | relocate_typevector (tv) |
271 | struct typevector *tv; |
272 | { |
273 | register int ntypes = TYPEVECTOR_NTYPES (tv); |
274 | register int i; |
275 | |
276 | for (i = 0; i < ntypes; i++) |
277 | RELOCATE (TYPEVECTOR_TYPE (tv, i)); |
278 | for (i = 0; i < ntypes; i++) |
279 | relocate_type (TYPEVECTOR_TYPE (tv, i)); |
280 | } |
281 | |
7b4ac7e1 |
282 | /* We cannot come up with an a priori spanning tree |
283 | for the network of types, since types can be used |
284 | for many symbols and also as components of other types. |
285 | Therefore, we need to be able to mark types that we |
286 | already have relocated (or are already in the middle of relocating) |
287 | as in a garbage collector. */ |
288 | |
289 | static void |
290 | relocate_type (tp) |
291 | register struct type *tp; |
292 | { |
293 | register int nfields = TYPE_NFIELDS (tp); |
294 | register int i; |
295 | |
296 | RELOCATE (TYPE_NAME (tp)); |
297 | RELOCATE (TYPE_TARGET_TYPE (tp)); |
298 | RELOCATE (TYPE_FIELDS (tp)); |
299 | RELOCATE (TYPE_POINTER_TYPE (tp)); |
300 | |
301 | for (i = 0; i < nfields; i++) |
302 | { |
303 | RELOCATE (TYPE_FIELD_TYPE (tp, i)); |
304 | RELOCATE (TYPE_FIELD_NAME (tp, i)); |
305 | } |
306 | } |
632ea0cc |
307 | |
308 | static void |
309 | relocate_sourcevector (svp) |
310 | register struct sourcevector *svp; |
311 | { |
312 | register int nfiles = svp->length; |
313 | register int i; |
314 | for (i = 0; i < nfiles; i++) |
315 | RELOCATE (svp->source[i]); |
316 | for (i = 0; i < nfiles; i++) |
317 | relocate_source (svp->source[i]); |
318 | } |
319 | |
320 | static void |
321 | relocate_source (sp) |
322 | register struct source *sp; |
323 | { |
324 | register int nitems = sp->contents.nitems; |
325 | register int i; |
326 | |
327 | RELOCATE (sp->name); |
328 | for (i = 0; i < nitems; i++) |
e91b87a3 |
329 | TEXT_RELOCATE (sp->contents.item[i].pc); |
632ea0cc |
330 | } |
7b4ac7e1 |
331 | \f |
332 | /* Read symsegs from file named NAME open on DESC, |
333 | make symtabs from them, and return a chain of them. |
632ea0cc |
334 | These symtabs are not suitable for direct use in `symtab_list' |
335 | because each one describes a single object file, perhaps many source files. |
336 | `symbol_file_command' takes each of these, makes many real symtabs |
337 | from it, and then frees it. |
338 | |
339 | We assume DESC is prepositioned at the end of the string table, |
7b4ac7e1 |
340 | just before the symsegs if there are any. */ |
341 | |
342 | struct symtab * |
343 | read_symsegs (desc, name) |
344 | int desc; |
345 | char *name; |
346 | { |
347 | struct symbol_root root; |
348 | register char *data; |
632ea0cc |
349 | register struct symtab *sp, *sp1, *chain = 0; |
7b4ac7e1 |
350 | register int len; |
351 | |
352 | while (1) |
353 | { |
354 | len = myread (desc, &root, sizeof root); |
355 | if (len == 0 || root.format == 0) |
356 | break; |
e91b87a3 |
357 | /* format 1 was ok for the original gdb, but since the size of the |
358 | type structure changed when C++ support was added, it can no |
359 | longer be used. Accept only format 2. */ |
360 | if (root.format != 2 || |
7b4ac7e1 |
361 | root.length < sizeof root) |
e91b87a3 |
362 | error ("\nInvalid symbol segment format code"); |
7b4ac7e1 |
363 | data = (char *) xmalloc (root.length); |
364 | bcopy (&root, data, sizeof root); |
365 | len = myread (desc, data + sizeof root, |
366 | root.length - sizeof root); |
367 | sp = relocate_symtab (data); |
632ea0cc |
368 | RELOCATE (((struct symbol_root *)data)->sourcevector); |
369 | relocate_sourcevector (((struct symbol_root *)data)->sourcevector); |
7b4ac7e1 |
370 | sp->next = chain; |
371 | chain = sp; |
632ea0cc |
372 | sp->linetable = (struct linetable *) ((struct symbol_root *)data)->sourcevector; |
7b4ac7e1 |
373 | } |
374 | |
375 | return chain; |
376 | } |
377 | \f |
378 | static int block_depth (); |
4187119d |
379 | void print_spaces (); |
7b4ac7e1 |
380 | static void print_symbol (); |
381 | |
e91b87a3 |
382 | void |
7b4ac7e1 |
383 | print_symtabs (filename) |
384 | char *filename; |
385 | { |
386 | FILE *outfile; |
387 | register struct symtab *s; |
388 | register int i, j; |
389 | int len, line, blen; |
390 | register struct linetable *l; |
391 | struct blockvector *bv; |
392 | register struct block *b; |
393 | int depth; |
394 | struct cleanup *cleanups; |
395 | extern int fclose(); |
396 | |
397 | if (filename == 0) |
398 | error_no_arg ("file to write symbol data in"); |
4187119d |
399 | |
400 | filename = tilde_expand (filename); |
401 | make_cleanup (free, filename); |
402 | |
7b4ac7e1 |
403 | outfile = fopen (filename, "w"); |
3bf57d21 |
404 | if (outfile == 0) |
405 | perror_with_name (filename); |
7b4ac7e1 |
406 | |
407 | cleanups = make_cleanup (fclose, outfile); |
408 | immediate_quit++; |
409 | |
410 | for (s = symtab_list; s; s = s->next) |
411 | { |
412 | /* First print the line table. */ |
413 | fprintf (outfile, "Symtab for file %s\n\n", s->filename); |
414 | fprintf (outfile, "Line table:\n\n"); |
415 | l = LINETABLE (s); |
416 | len = l->nitems; |
417 | for (i = 0; i < len; i++) |
e91b87a3 |
418 | fprintf (outfile, " line %d at %x\n", l->item[i].line, |
419 | l->item[i].pc); |
7b4ac7e1 |
420 | /* Now print the block info. */ |
421 | fprintf (outfile, "\nBlockvector:\n\n"); |
422 | bv = BLOCKVECTOR (s); |
423 | len = BLOCKVECTOR_NBLOCKS (bv); |
424 | for (i = 0; i < len; i++) |
425 | { |
426 | b = BLOCKVECTOR_BLOCK (bv, i); |
427 | depth = block_depth (b) * 2; |
428 | print_spaces (depth, outfile); |
429 | fprintf (outfile, "block #%03d (object 0x%x) ", i, b); |
430 | fprintf (outfile, "[0x%x..0x%x]", BLOCK_START (b), BLOCK_END (b)); |
431 | if (BLOCK_SUPERBLOCK (b)) |
432 | fprintf (outfile, " (under 0x%x)", BLOCK_SUPERBLOCK (b)); |
433 | if (BLOCK_FUNCTION (b)) |
434 | fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b))); |
435 | fputc ('\n', outfile); |
436 | blen = BLOCK_NSYMS (b); |
437 | for (j = 0; j < blen; j++) |
438 | { |
439 | print_symbol (BLOCK_SYM (b, j), depth + 1, outfile); |
440 | } |
441 | } |
442 | |
443 | fprintf (outfile, "\n\n"); |
444 | } |
445 | |
446 | immediate_quit--; |
447 | do_cleanups (cleanups); |
448 | } |
449 | |
450 | static void |
451 | print_symbol (symbol, depth, outfile) |
452 | struct symbol *symbol; |
453 | int depth; |
454 | FILE *outfile; |
455 | { |
456 | print_spaces (depth, outfile); |
457 | if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE) |
458 | { |
7a67dd45 |
459 | fprintf (outfile, "label %s at 0x%x\n", SYMBOL_NAME (symbol), |
7b4ac7e1 |
460 | SYMBOL_VALUE (symbol)); |
461 | return; |
462 | } |
463 | if (SYMBOL_NAMESPACE (symbol) == STRUCT_NAMESPACE) |
464 | { |
465 | if (TYPE_NAME (SYMBOL_TYPE (symbol))) |
466 | { |
467 | type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth); |
468 | } |
469 | else |
470 | { |
471 | fprintf (outfile, "%s %s = ", |
472 | (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM |
473 | ? "enum" |
474 | : (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT |
475 | ? "struct" : "union")), |
476 | SYMBOL_NAME (symbol)); |
477 | type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth); |
478 | } |
479 | fprintf (outfile, ";\n"); |
480 | } |
481 | else |
482 | { |
483 | if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF) |
484 | fprintf (outfile, "typedef "); |
485 | if (SYMBOL_TYPE (symbol)) |
486 | { |
487 | type_print_1 (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol), |
488 | outfile, 1, depth); |
489 | fprintf (outfile, "; "); |
490 | } |
491 | else |
492 | fprintf (outfile, "%s ", SYMBOL_NAME (symbol)); |
493 | |
494 | switch (SYMBOL_CLASS (symbol)) |
495 | { |
496 | case LOC_CONST: |
497 | fprintf (outfile, "const %d (0x%x),", |
498 | SYMBOL_VALUE (symbol), SYMBOL_VALUE (symbol)); |
499 | break; |
500 | |
501 | case LOC_CONST_BYTES: |
502 | fprintf (outfile, "const %d hex bytes:", |
503 | TYPE_LENGTH (SYMBOL_TYPE (symbol))); |
504 | { |
505 | int i; |
506 | for (i = 0; i < TYPE_LENGTH (SYMBOL_TYPE (symbol)); i++) |
507 | fprintf (outfile, " %2x", SYMBOL_VALUE_BYTES (symbol) [i]); |
508 | fprintf (outfile, ","); |
509 | } |
510 | break; |
511 | |
512 | case LOC_STATIC: |
513 | fprintf (outfile, "static at 0x%x,", SYMBOL_VALUE (symbol)); |
514 | break; |
515 | |
516 | case LOC_REGISTER: |
517 | fprintf (outfile, "register %d,", SYMBOL_VALUE (symbol)); |
518 | break; |
519 | |
520 | case LOC_ARG: |
521 | fprintf (outfile, "arg at 0x%x,", SYMBOL_VALUE (symbol)); |
522 | break; |
523 | |
4187119d |
524 | case LOC_REF_ARG: |
525 | fprintf (outfile, "reference arg at 0x%x,", SYMBOL_VALUE (symbol)); |
526 | break; |
527 | |
bb7592f0 |
528 | case LOC_REGPARM: |
e91b87a3 |
529 | fprintf (outfile, "parameter register %d,", SYMBOL_VALUE (symbol)); |
bb7592f0 |
530 | break; |
531 | |
7b4ac7e1 |
532 | case LOC_LOCAL: |
533 | fprintf (outfile, "local at 0x%x,", SYMBOL_VALUE (symbol)); |
534 | break; |
535 | |
536 | case LOC_TYPEDEF: |
537 | break; |
538 | |
539 | case LOC_LABEL: |
540 | fprintf (outfile, "label at 0x%x", SYMBOL_VALUE (symbol)); |
541 | break; |
542 | |
543 | case LOC_BLOCK: |
544 | fprintf (outfile, "block (object 0x%x) starting at 0x%x,", |
545 | SYMBOL_VALUE (symbol), |
546 | BLOCK_START (SYMBOL_BLOCK_VALUE (symbol))); |
547 | break; |
548 | } |
549 | } |
550 | fprintf (outfile, "\n"); |
551 | } |
552 | |
553 | /* Return the nexting depth of a block within other blocks in its symtab. */ |
554 | |
555 | static int |
556 | block_depth (block) |
557 | struct block *block; |
558 | { |
559 | register int i = 0; |
560 | while (block = BLOCK_SUPERBLOCK (block)) i++; |
561 | return i; |
562 | } |
563 | \f |
e91b87a3 |
564 | /* |
565 | * Free all partial_symtab storage. |
566 | */ |
567 | void |
568 | free_all_psymtabs() |
569 | { |
570 | obstack_free (psymbol_obstack, 0); |
571 | obstack_init (psymbol_obstack); |
572 | partial_symtab_list = (struct partial_symtab *) 0; |
573 | } |
574 | \f |
575 | void |
576 | _initialize_symmisc () |
7b4ac7e1 |
577 | { |
e91b87a3 |
578 | symtab_list = (struct symtab *) 0; |
579 | partial_symtab_list = (struct partial_symtab *) 0; |
580 | |
7b4ac7e1 |
581 | add_com ("printsyms", class_obscure, print_symtabs, |
582 | "Print dump of current symbol definitions to file OUTFILE."); |
583 | } |
584 | |