|
|
1.1 root 1: /* Output GDB-format symbol table information from GNU compiler.
2: Copyright (C) 1987, 1988 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: #include "config.h"
23: #include "tree.h"
24: #include "symseg.h"
25: #include "rtl.h"
26: #include "gdbfiles.h"
27: #include <stdio.h>
28:
29: /* Get N_SO from stab.h if we can expect the file to exist. */
30: #ifndef NO_DBX_FORMAT
31: #include <stab.h>
32: #endif
33:
34: /* .stabs code for source file name. */
35: #ifndef N_SO
36: #define N_SO 0x64
37: #endif
38:
39: /* Unix maximum on file name length. Needed for getwd. */
40: #define MAXNAMLEN 1024
41:
42: /* Get the number to output for a reference to type TYPE. */
43: #define TYPE_OUTPUT_ADDRESS(TYPE) \
44: TYPE_SYMTAB_ADDRESS (TYPE_MAIN_VARIANT (TYPE))
45:
46: /* Stream for writing symbol table file. */
47: static FILE *symfile;
48:
49: /* Name of symbol table file. */
50: static char *symfile_name;
51:
52: /* Stream for writing to assembler file. */
53: static FILE *asmfile;
54:
55: /* Address for allocating space in symbol table file.
56: Changes in this variable are paired globally with writes to symfile,
57: but often we allocate many structures, advancing next_address,
58: before writing any of them. */
59: static int next_address;
60:
61: /* Chain recording all the types that have been output,
62: giving the address-in-the-symseg of each one. */
63:
64: struct typevec_elt
65: {
66: int address;
67: struct typevec_elt *next;
68: };
69:
70: static struct typevec_elt *typevec;
71:
72: /* Number of types recorded so far in the chain. */
73:
74: static int total_types;
75:
76: /* `blockvec' is a chain recording all the symbol-blocks that have been output,
77: giving the address-in-the-symseg of each one. */
78:
79: struct blockvec_elt
80: {
81: int address;
82: struct blockvec_elt *next;
83: };
84:
85: static struct blockvec_elt *blockvec;
86:
87: /* Number of blocks recorded so far in the chain. */
88:
89: static int total_blocks;
90:
91: static void symout_range_bounds ();
92: static void symout_array_domain ();
93: static void symout_record_fields ();
94: static void symout_enum_values ();
95: static void symout_record_field_names ();
96: static void symout_enum_value_names ();
97: static int subrange_p ();
98: static void symout_strings_skip ();
99: static void symout_strings_print ();
100:
101: /* At the beginning of compilation, start writing the symbol table.
102: Initialize the type and block chain.
103: Also open and initialize the symseg file. */
104:
105: void
106: symout_init (filename, asm_file, sourcename)
107: char *filename;
108: FILE *asm_file;
109: char *sourcename;
110: {
111: struct symbol_root buffer;
112:
113: #ifdef VMS
114: fatal ("Cannot write GDB debugging format on VMS");
115: #endif
116:
117: asmfile = asm_file;
118: fprintf (asmfile, ".text 0\n.gdbbeg 0\n.gdbbeg 1\n");
119: fprintf (asmfile,
120: "Ltext:\t.stabs \"%s\",%d,0,0,Ltext\n",
121: sourcename, N_SO);
122: fprintf (asmfile, ".data 0\nLdata:\n");
123: ASM_OUTPUT_LOCAL (asmfile, "Lbss", 0);
124: fprintf (asmfile, ".gdbsym Ldata,%d\n",
125: (char *) &buffer.databeg - (char *) &buffer);
126: fprintf (asmfile, ".gdbsym Lbss,%d\n",
127: (char *) &buffer.bssbeg - (char *) &buffer);
128:
129: symfile = fopen (filename, "w");
130: if (symfile == 0)
131: pfatal_with_name (symfile);
132: symfile_name = (char *) malloc (strlen (filename) + 1);
133: strcpy (symfile_name, filename);
134:
135: typevec = 0;
136: blockvec = 0;
137: total_types = 0;
138: total_blocks = 0;
139:
140: bzero (&buffer, sizeof buffer);
141: fwrite (&buffer, sizeof buffer, 1, symfile);
142:
143: next_address = sizeof buffer;
144: }
145:
146: /* Functions for outputting strings into the symbol table.
147: The string to be output is effectively the concatenation of
148: the two strings P1 and P2. Their lengths are given as S1 and S2.
149: If P1 or P2 is zero, that string is not used.
150:
151: A null character is output to terminate the string,
152: and it is followed by more nulls as padding to a word boundary. */
153:
154: static void
155: symout_strings (p1, s1, p2, s2)
156: char *p1;
157: int s1;
158: char *p2;
159: int s2;
160: {
161: symout_strings_print (p1, s1, p2, s2);
162: symout_strings_skip (p1, s1, p2, s2);
163: }
164:
165: /* Like symout_strings but only output; do not update next_address. */
166:
167: static void
168: symout_strings_print (p1, s1, p2, s2)
169: char *p1;
170: int s1;
171: char *p2;
172: int s2;
173: {
174: register int total;
175:
176: if (p1 && s1 == 0)
177: s1 = strlen (p1);
178: if (p2 && s2 == 0)
179: s2 = strlen (p2);
180:
181: if (p1)
182: fwrite (p1, s1, 1, symfile);
183: if (p2)
184: fwrite (p2, s2, 1, symfile);
185: putc (0, symfile);
186:
187: total = s1 + s2 + 1;
188: while (total % sizeof (int))
189: {
190: putc (0, symfile);
191: total++;
192: }
193: }
194:
195: /* Like symout_strings but just update next_address; do not output. */
196:
197: static void
198: symout_strings_skip (p1, s1, p2, s2)
199: char *p1;
200: int s1;
201: char *p2;
202: int s2;
203: {
204: register int total;
205:
206: if (p1 && s1 == 0)
207: s1 = strlen (p1);
208: if (p2 && s2 == 0)
209: s2 = strlen (p2);
210:
211: total = s1 + s2 + 1;
212: while (total % sizeof (int))
213: total++;
214:
215: next_address += total;
216: }
217:
218: /* Call here to output a chain of types.
219: After each function, this is done first for the chain of permanent types
220: made during the function, and then for the chain of temporary types.
221: This must be done before outputting the symbols and blocks of the function.
222:
223: At the end of compilation, this is done for all the permanent types
224: made since the last function.
225:
226: Each permanent type is done once, at the beginning of the next function,
227: or at the end of the compilation if no functions follow.
228: Once a type has been processed here, its TYPE_SYMTAB_ADDRESS remains
229: set up. */
230:
231: void
232: symout_types (types)
233: tree types;
234: {
235: struct typerec
236: {
237: int number;
238: int address;
239: int nfields;
240: int fields_address;
241: int name_address;
242: char *name;
243: char *name_prefix;
244: };
245:
246: register int n_types, i;
247: register struct typerec *records;
248: register tree next;
249: struct type buffer;
250:
251: for (next = types, n_types = 0;
252: next;
253: next = TREE_CHAIN (next), n_types++);
254:
255: records = (struct typerec *) alloca (n_types * sizeof (struct typerec));
256:
257: for (next = types, i = 0;
258: next;
259: next = TREE_CHAIN (next), i++)
260: {
261: register struct typevec_elt *velt
262: = (struct typevec_elt *) xmalloc (sizeof (struct typevec_elt));
263: velt->next = typevec;
264: typevec = velt;
265:
266: total_types++;
267:
268: if (TYPE_NAME (next))
269: {
270: records[i].name_address = next_address;
271:
272: if (TREE_CODE (TYPE_NAME (next)) == IDENTIFIER_NODE)
273: {
274: records[i].name = IDENTIFIER_POINTER (TYPE_NAME (next));
275: switch (TREE_CODE (next))
276: {
277: case RECORD_TYPE:
278: records[i].name_prefix = "struct ";
279: break;
280:
281: case UNION_TYPE:
282: records[i].name_prefix = "union ";
283: break;
284:
285: case ENUMERAL_TYPE:
286: records[i].name_prefix = "enum ";
287: break;
288: }
289: }
290: else
291: {
292: records[i].name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (next)));
293: records[i].name_prefix = 0;
294: }
295: symout_strings_skip (records[i].name_prefix, 0,
296: records[i].name, 0);
297:
298: }
299: else
300: {
301: records[i].name = 0;
302: records[i].name_address = 0;
303: records[i].name_prefix = 0;
304: }
305:
306: records[i].address = next_address;
307: TYPE_SYMTAB_ADDRESS (next) = next_address;
308: velt->address = next_address;
309: next_address += sizeof (struct type);
310: records[i].nfields = 0;
311: records[i].fields_address = 0;
312: switch (TREE_CODE (next))
313: {
314: case ARRAY_TYPE:
315: records[i].nfields
316: = (TYPE_DOMAIN(next)
317: ? ! integer_zerop (TYPE_MIN_VALUE (TYPE_DOMAIN (next)))
318: : 0 );
319: break;
320:
321: case INTEGER_TYPE:
322: if (subrange_p (next))
323: buffer.nfields = 2;
324: break;
325:
326: case RECORD_TYPE:
327: case UNION_TYPE:
328: case ENUMERAL_TYPE:
329: records[i].nfields = list_length (TYPE_FIELDS (next));
330: }
331: if (records[i].nfields)
332: records[i].fields_address = next_address;
333: next_address += records[i].nfields * sizeof (struct field);
334: }
335:
336: for (next = types, i = 0;
337: next;
338: next = TREE_CHAIN (next), i++)
339: {
340: if (records[i].name)
341: symout_strings_print (records[i].name_prefix, 0,
342: records[i].name, 0);
343:
344: if (TYPE_SIZE (next) == 0)
345: buffer.length = 0;
346: else
347: buffer.length
348: = (TREE_INT_CST_LOW (TYPE_SIZE (next))
349: * TYPE_SIZE_UNIT (next) / BITS_PER_UNIT);
350: buffer.name = (char *) records[i].name_address;
351: buffer.target_type = (struct type *) (TREE_TYPE (next) ? TYPE_OUTPUT_ADDRESS (TREE_TYPE (next)) : 0);
352:
353: buffer.pointer_type = 0;
354: buffer.function_type = 0;
355: buffer.flags
356: = ((TREE_CODE (next) == INTEGER_TYPE || TREE_CODE (next) == ENUMERAL_TYPE)
357: && TREE_UNSIGNED (next))
358: ? TYPE_FLAG_UNSIGNED : 0;
359: buffer.nfields = records[i].nfields;
360: buffer.fields = (struct field *) records[i].fields_address;
361:
362: switch (TREE_CODE (next))
363: {
364: case INTEGER_TYPE:
365: buffer.code = TYPE_CODE_INT;
366: if (buffer.nfields)
367: buffer.code = TYPE_CODE_RANGE;
368: break;
369:
370: case REAL_TYPE:
371: buffer.code = TYPE_CODE_FLT;
372: break;
373:
374: case VOID_TYPE:
375: buffer.code = TYPE_CODE_VOID;
376: break;
377:
378: case POINTER_TYPE:
379: buffer.code = TYPE_CODE_PTR;
380: break;
381:
382: case ARRAY_TYPE:
383: if (buffer.nfields == 0)
384: buffer.code = TYPE_CODE_ARRAY;
385: else
386: buffer.code = TYPE_CODE_PASCAL_ARRAY;
387: break;
388:
389: case RECORD_TYPE:
390: buffer.code = TYPE_CODE_STRUCT;
391: break;
392:
393: case UNION_TYPE:
394: buffer.code = TYPE_CODE_UNION;
395: break;
396:
397: case FUNCTION_TYPE:
398: buffer.code = TYPE_CODE_FUNC;
399: break;
400:
401: case ENUMERAL_TYPE:
402: buffer.code = TYPE_CODE_ENUM;
403: break;
404:
405: default:
406: abort ();
407: }
408:
409: fwrite (&buffer, sizeof buffer, 1, symfile);
410:
411: switch (TREE_CODE (next))
412: {
413: case ARRAY_TYPE:
414: if (buffer.nfields)
415: symout_array_domain (next);
416: break;
417:
418: case RECORD_TYPE:
419: case UNION_TYPE:
420: symout_record_fields (next);
421: break;
422:
423: case ENUMERAL_TYPE:
424: symout_enum_values (next);
425: break;
426:
427: case INTEGER_TYPE:
428: if (buffer.nfields)
429: symout_range_bounds (next);
430: }
431: }
432:
433: for (next = types, i = 0;
434: next;
435: next = TREE_CHAIN (next), i++)
436: {
437: switch (TREE_CODE (next))
438: {
439: case RECORD_TYPE:
440: case UNION_TYPE:
441: symout_record_field_names (next);
442: break;
443:
444: case ENUMERAL_TYPE:
445: symout_enum_value_names (next);
446: break;
447: }
448: }
449: }
450:
451: /* Return nonzero if TYPE's range of possible values
452: is not the full range allowed by the number of bits it has.
453: TYPE is assumed to be an INTEGER_TYPE or ENUMERAL_TYPE. */
454:
455: static int
456: subrange_p (type)
457: tree type;
458: {
459: int uns = TREE_UNSIGNED (type);
460:
461: if (TYPE_PRECISION (type) >= HOST_BITS_PER_INT)
462: {
463: if (uns)
464: return integer_zerop (TYPE_MIN_VALUE (type))
465: && TREE_INT_CST_LOW (TYPE_MAX_VALUE (type)) == 0
466: && (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (type))
467: == (1 << (TYPE_PRECISION (type) - HOST_BITS_PER_INT)) - 1);
468: return TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0
469: && TREE_INT_CST_LOW (TYPE_MAX_VALUE (type)) == 0
470: && (TREE_INT_CST_HIGH (TYPE_MIN_VALUE (type))
471: == (-1) << (TYPE_PRECISION (type) - 1 - HOST_BITS_PER_INT))
472: && (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (type))
473: == (1 << (TYPE_PRECISION (type) - 1 - HOST_BITS_PER_INT)) - 1);
474: }
475:
476: if (uns)
477: return integer_zerop (TYPE_MIN_VALUE (type))
478: && (TREE_INT_CST_LOW (TYPE_MAX_VALUE (type))
479: == (1 << TYPE_PRECISION (type)) - 1);
480: else
481: return (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type))
482: == (-1) << (TYPE_PRECISION (type) - 1))
483: && (TREE_INT_CST_LOW (TYPE_MAX_VALUE (type))
484: == (1 << (TYPE_PRECISION (type) - 1)) - 1);
485: }
486:
487: /* Functions to output the "fields" of various kinds of types.
488: These assume that next_address has already been incremented to
489: cover these fields, and the fields of all the other types being
490: output in this batch; so next_address can be used to allocate
491: space to store field names, etc. */
492:
493: static void
494: symout_array_domain (type)
495: tree type;
496: {
497: struct field buffer;
498:
499: buffer.bitpos = 0;
500: buffer.bitsize = 0;
501: buffer.type = (struct type *) TYPE_OUTPUT_ADDRESS (TYPE_DOMAIN (type));
502: buffer.name = 0;
503: fwrite (&buffer, sizeof (struct field), 1, symfile);
504: }
505:
506: static void
507: symout_range_bounds (type)
508: tree type;
509: {
510: struct field buffer;
511:
512: buffer.bitpos = TREE_INT_CST_LOW (TYPE_MIN_VALUE (type));
513: buffer.bitsize = 0;
514: buffer.type = (struct type *) TYPE_OUTPUT_ADDRESS (type);
515: buffer.name = 0;
516: fwrite (&buffer, sizeof (struct field), 1, symfile);
517:
518: buffer.bitpos = TREE_INT_CST_LOW (TYPE_MAX_VALUE (type));
519: buffer.bitsize = 0;
520: buffer.type = (struct type *) TYPE_OUTPUT_ADDRESS (type);
521: buffer.name = 0;
522: fwrite (&buffer, sizeof (struct field), 1, symfile);
523: }
524:
525: static void
526: symout_record_fields (type)
527: tree type;
528: {
529: struct field buffer;
530: register tree field;
531:
532: for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
533: {
534: buffer.bitpos = DECL_OFFSET (field);
535: buffer.bitsize
536: = (TREE_PACKED (field)
537: ? TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field)
538: : 0);
539: buffer.type = (struct type *) TYPE_OUTPUT_ADDRESS (TREE_TYPE (field));
540: if (DECL_NAME (field))
541: {
542: buffer.name = (char *) next_address;
543: symout_strings_skip (0, IDENTIFIER_LENGTH (DECL_NAME (field)), 0, 0);
544: }
545: else
546: buffer.name = 0;
547: fwrite (&buffer, sizeof (struct field), 1, symfile);
548: }
549: }
550:
551: static void
552: symout_enum_values (type)
553: tree type;
554: {
555: struct field buffer;
556: register tree link, value;
557:
558: for (link = TYPE_VALUES (type); link; link = TREE_CHAIN (link))
559: {
560: value = TREE_VALUE (link);
561: buffer.bitpos = TREE_INT_CST_LOW (value);
562: buffer.bitsize = 0;
563: buffer.type = (struct type *) TYPE_OUTPUT_ADDRESS (type);
564: buffer.name = (char *) next_address;
565: symout_strings_skip (0, IDENTIFIER_LENGTH (TREE_PURPOSE (link)), 0, 0);
566: fwrite (&buffer, sizeof buffer, 1, symfile);
567: }
568: }
569:
570: /* Output field names or value names for the fields of a type.
571: This is called, for the types that need it, after the fields
572: have been output for all the types in the batch.
573: We do not update next_address here, because it has already been
574: updated for all the names in all the fields in all the types. */
575:
576: static void
577: symout_record_field_names (type)
578: tree type;
579: {
580: register tree field;
581:
582: for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
583: if (DECL_NAME (field))
584: symout_strings_print (IDENTIFIER_POINTER (DECL_NAME (field)),
585: IDENTIFIER_LENGTH (DECL_NAME (field)),
586: 0, 0);
587: }
588:
589: static void
590: symout_enum_value_names (type)
591: tree type;
592: {
593: register tree value;
594:
595: for (value = TYPE_VALUES (type); value; value = TREE_CHAIN (value))
596: symout_strings_print (IDENTIFIER_POINTER (TREE_PURPOSE (value)),
597: IDENTIFIER_LENGTH (TREE_PURPOSE (value)),
598: 0, 0);
599: }
600:
601: /* Output the symbols of a block, given the list of decl nodes.
602: Store the file addresses at which the symbols are output
603: into ADDR_BUFFER, a vector which has just the right length.
604:
605: If FILTER is 1, do only the private symbols in DECLS.
606: If FILTER is 2, do only the public ones (but no externals).
607: If FILTER is 0, do all (except external functions). */
608:
609: static void
610: symout_block_symbols (decls, addr_buffer, filter)
611: tree decls;
612: int *addr_buffer;
613: int filter;
614: {
615: register tree decl;
616: struct symbol buffer;
617: register int i;
618:
619: for (decl = decls, i = 0; decl; decl = TREE_CHAIN (decl))
620: {
621: register name_address = next_address;
622:
623: if (filter == (TREE_PUBLIC (decl) ? 1 : 2))
624: continue;
625:
626: /* Do not mention external functions.
627: Let their own files mention them.
628: In the top blocks, don't mention external anything. */
629:
630: if (TREE_EXTERNAL (decl)
631: && (filter || TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE))
632: continue;
633:
634: if (TREE_TYPE (decl) == error_mark_node)
635: continue;
636:
637: symout_strings (IDENTIFIER_POINTER (DECL_NAME (decl)),
638: IDENTIFIER_LENGTH (DECL_NAME (decl)),
639: 0, 0);
640: addr_buffer[i] = next_address;
641: buffer.name = (char *) name_address;
642: buffer.namespace = VAR_NAMESPACE;
643: buffer.type = (struct type *) TYPE_OUTPUT_ADDRESS (TREE_TYPE (decl));
644: switch (TREE_CODE (decl))
645: {
646: case PARM_DECL:
647: buffer.class = LOC_ARG;
648: buffer.value.value = DECL_OFFSET (decl) / BITS_PER_UNIT;
649: break;
650:
651: case VAR_DECL:
652: case RESULT_DECL:
653: if (TREE_STATIC (decl) || TREE_EXTERNAL (decl))
654: {
655: if (! TREE_PUBLIC (decl) || DECL_INITIAL (decl))
656: {
657: char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
658: fprintf (asmfile, "\t.gdbsym ");
659: ASM_OUTPUT_LABELREF (asmfile, str);
660: fprintf (asmfile, ",%d\n",
661: next_address + (char *)&buffer.value - (char *)&buffer);
662: buffer.class = LOC_STATIC;
663: }
664: else
665: /* Uninitialized public symbols are output as .comm;
666: Tell GDB to get address from loader global symbol.
667: Also come here for symbols declared extern. */
668: buffer.class = LOC_EXTERNAL;
669: }
670: else
671: {
672: if (GET_CODE (DECL_RTL (decl)) == REG)
673: {
674: buffer.class = LOC_REGISTER;
675: buffer.value.value = REGNO (DECL_RTL (decl));
676: /* Detect vars that were optimized entirely away. */
677: if (buffer.value.value == -1)
678: buffer.class = LOC_CONST;
679: }
680: /* Locals in memory are expected to be addressed as
681: (PLUS (REG ...) (CONST_INT ...)).
682: Bomb out if that is not so. */
683: else if (GET_CODE (DECL_RTL (decl)) == MEM)
684: {
685: register rtx addr = XEXP (DECL_RTL (decl), 0);
686: if (GET_CODE (addr) != PLUS && GET_CODE (addr) != MINUS)
687: abort ();
688: if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
689: abort ();
690: buffer.class = LOC_LOCAL;
691: buffer.value.value = INTVAL (XEXP (addr, 1));
692: if (GET_CODE (addr) == MINUS)
693: buffer.value.value = - buffer.value.value;
694: }
695: else
696: abort ();
697: }
698: break;
699:
700: case TYPE_DECL:
701: buffer.class = LOC_TYPEDEF;
702: buffer.value.value = 0;
703: break;
704:
705: case CONST_DECL:
706: buffer.class = LOC_CONST;
707: buffer.value.value = TREE_INT_CST_LOW (DECL_INITIAL (decl));
708: break;
709:
710: case FUNCTION_DECL:
711: if (DECL_INITIAL (decl))
712: {
713: buffer.class = LOC_BLOCK;
714: buffer.value.value = DECL_BLOCK_SYMTAB_ADDRESS (decl);
715: }
716: else
717: buffer.class = LOC_EXTERNAL;
718: }
719:
720: fwrite (&buffer, sizeof buffer, 1, symfile);
721: next_address += sizeof buffer;
722: i++;
723: }
724: }
725:
726: /* Output the tags (struct, union and enum definitions) for a block,
727: given a list of them (a chain of TREE_LIST nodes) in TAGS.
728: Store their addresses in the file into ADDR_BUFFER. */
729:
730: static void
731: symout_block_tags (tags, addr_buffer)
732: tree tags;
733: int *addr_buffer;
734: {
735: register tree tag;
736: struct symbol buffer;
737: register int i;
738:
739: for (tag = tags, i = 0; tag; tag = TREE_CHAIN (tag), i++)
740: {
741: buffer.name = (char *) next_address;
742:
743: symout_strings (IDENTIFIER_POINTER (TREE_PURPOSE (tag)),
744: IDENTIFIER_LENGTH (TREE_PURPOSE (tag)),
745: 0, 0);
746: addr_buffer[i] = next_address;
747: buffer.namespace = STRUCT_NAMESPACE;
748: buffer.type = (struct type *) TYPE_OUTPUT_ADDRESS (TREE_VALUE (tag));
749: buffer.class = LOC_TYPEDEF;
750: buffer.value.value = 0;
751:
752: fwrite (&buffer, sizeof buffer, 1, symfile);
753: next_address += sizeof buffer;
754: }
755: }
756:
757: /* Output all the data structure for a "block"
758: (any binding contour).
759: DECLS is the chain of declarations of variables in this block.
760: TAGS is the list of struct, union and enum tag definitions of this block.
761: SUPERBLOCK_ADDRESS is the symtab file address of the containing block's
762: data structure. */
763:
764: int
765: symout_block (decls, tags, args, superblock_address)
766: tree decls;
767: tree tags;
768: tree args;
769: int superblock_address;
770: {
771: register tree decl;
772: register int i;
773: register int *addr_buffer;
774: struct block buffer;
775: int n_decls, n_tags, n_args, total;
776: register struct blockvec_elt *velt;
777: int block_address;
778:
779: for (decl = decls, i = 0; decl; decl = TREE_CHAIN (decl))
780: if (! TREE_EXTERNAL (decl)
781: || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE)
782: i++;
783:
784: n_decls = i;
785:
786: for (decl = args, i = 0; decl; decl = TREE_CHAIN (decl), i++);
787: n_args = i;
788:
789: for (decl = tags, i = 0; decl; decl = TREE_CHAIN (decl), i++);
790: n_tags = i;
791:
792: total = n_decls + n_args + n_tags;
793:
794: addr_buffer = (int *) alloca (total * sizeof (int));
795:
796: symout_block_symbols (args, addr_buffer, 0);
797: symout_block_symbols (decls, addr_buffer + n_args, 0);
798: symout_block_tags (tags, addr_buffer + n_decls + n_args);
799:
800: velt = (struct blockvec_elt *) xmalloc (sizeof (struct blockvec_elt));
801: velt->next = blockvec;
802: velt->address = next_address;
803: blockvec = velt;
804:
805: buffer.startaddr = 0;
806: buffer.endaddr = 0;
807: buffer.superblock = (struct block *) superblock_address;
808: buffer.function = 0;
809: buffer.nsyms = total;
810:
811: block_address = next_address;
812: fwrite (&buffer, sizeof buffer - sizeof buffer.sym, 1, symfile);
813: next_address += sizeof buffer - sizeof buffer.sym;
814:
815: fwrite (addr_buffer, sizeof (int), total, symfile);
816: next_address += total * sizeof (int);
817:
818: fprintf (asmfile, "\t.gdbblock %d,%d\n", total_blocks + 2, block_address);
819: total_blocks++;
820:
821: return block_address;
822: }
823:
824: /* Walk STMT, the body of a function, and output symtab data on
825: all the blocks that compose it and all symbols inside them.
826: ARGS is a chain of decls for argument variables of the function.
827: SUPERBLOCK_ADDRESS is the address of symbol data for the
828: innermost block containing STMT; it is used for recursive calls,
829: and is always 0 for the outermost call (since the containing
830: block for a function is output later than the function). */
831:
832: int
833: symout_function (stmt, args, superblock_address)
834: register tree stmt;
835: tree args;
836: int superblock_address;
837: {
838: int address = superblock_address;
839:
840: while (stmt)
841: {
842: switch (TREE_CODE (stmt))
843: {
844: case COMPOUND_STMT:
845: case LOOP_STMT:
846: symout_function (STMT_BODY (stmt), 0, address);
847: break;
848:
849: case IF_STMT:
850: symout_function (STMT_THEN (stmt), 0, address);
851: symout_function (STMT_ELSE (stmt), 0, address);
852: break;
853:
854: case LET_STMT:
855: address =
856: symout_block (STMT_VARS (stmt), STMT_TYPE_TAGS (stmt), args,
857: superblock_address);
858:
859: symout_function (STMT_BODY (stmt), 0, address);
860: }
861: stmt = TREE_CHAIN (stmt);
862: }
863: return address;
864: }
865:
866: /* Output all the data structure for a top two blocks in a compilation.
867: The top block is for public (global) symbols;
868: the next one is for private (this file only) symbols.
869:
870: DECLS is the chain of declarations of variables in this block.
871: TAGS is the list of struct, union and enum tag definitions. */
872:
873: void
874: symout_top_blocks (decls, tags)
875: tree decls;
876: tree tags;
877: {
878: register tree decl;
879: register int i;
880: register int *addr_buffer;
881: struct block buffer;
882: int n_decls, n_tags;
883: register struct blockvec_elt *velt;
884: int top_block_addr;
885:
886: /* First do the public-symbols block. */
887:
888: for (decl = decls, i = 0; decl; decl = TREE_CHAIN (decl))
889: if (TREE_PUBLIC (decl) && ! TREE_EXTERNAL (decl))
890: i++;
891: n_decls = i;
892:
893: addr_buffer = (int *) alloca (n_decls * sizeof (int));
894:
895: symout_block_symbols (decls, addr_buffer, 2);
896:
897: fprintf (asmfile, ".text 0\n\t.gdbend 0\n");
898: fprintf (asmfile, "\t.gdbblock 0,%d\n", next_address);
899:
900: total_blocks++;
901: velt = (struct blockvec_elt *) xmalloc (sizeof (struct blockvec_elt));
902: velt->next = blockvec;
903: velt->address = next_address;
904: blockvec = velt;
905:
906: top_block_addr = next_address;
907:
908: buffer.startaddr = 0;
909: buffer.endaddr = 0;
910: buffer.superblock = 0;
911: buffer.function = 0;
912: buffer.nsyms = n_decls;;
913:
914: fwrite (&buffer, sizeof buffer - sizeof buffer.sym, 1, symfile);
915: next_address += sizeof buffer - sizeof buffer.sym;
916:
917: fwrite (addr_buffer, sizeof (int), n_decls, symfile);
918: next_address += n_decls * sizeof (int);
919:
920: /* Next do the private-symbols block. */
921:
922: for (decl = decls, i = 0; decl; decl = TREE_CHAIN (decl))
923: if (! TREE_PUBLIC (decl) && ! TREE_EXTERNAL (decl))
924: i++;
925: n_decls = i;
926:
927: for (decl = tags, i = 0; decl; decl = TREE_CHAIN (decl), i++);
928: n_tags = i;
929:
930: addr_buffer = (int *) alloca ((n_decls + n_tags) * sizeof (int));
931:
932: symout_block_symbols (decls, addr_buffer, 1);
933: symout_block_tags (tags, addr_buffer + n_decls);
934:
935: fprintf (asmfile, "\t.gdbend 1\n");
936: fprintf (asmfile, "\t.gdbblock 1,%d\n", next_address);
937:
938: total_blocks++;
939: velt = (struct blockvec_elt *) xmalloc (sizeof (struct blockvec_elt));
940: velt->next = blockvec;
941: velt->address = next_address;
942: blockvec = velt;
943:
944: buffer.startaddr = 0;
945: buffer.endaddr = 0;
946: buffer.superblock = (struct block *) top_block_addr;
947: buffer.function = 0;
948: buffer.nsyms = n_decls + n_tags;;
949:
950: fwrite (&buffer, sizeof buffer - sizeof buffer.sym, 1, symfile);
951: next_address += sizeof buffer - sizeof buffer.sym;
952:
953: fwrite (addr_buffer, sizeof (int), n_decls + n_tags, symfile);
954: next_address += (n_decls + n_tags) * sizeof (int);
955: }
956:
957: /* Output the source-line-number information. */
958:
959: /* Output a `struct source' for the source file described by F.
960: Return the address-in-the-symseg of the `struct source'. */
961:
962: static int
963: symout_source_file (f)
964: struct gdbfile *f;
965: {
966: /* Make the `struct source' big enough for as many lines as
967: this file has. */
968: int size = sizeof (struct source) + (f->nlines - 1) * sizeof (struct line);
969: struct source *buffer
970: = (struct source *) alloca (size);
971: int addr;
972:
973: /* Use zero for the line data, since assembler will store the real data. */
974: bzero (buffer, size);
975:
976: /* Output the file's name as a string. The assembler doesn't know this. */
977: buffer->name = (char *) next_address;
978: symout_strings (f->name, 0, 0, 0);
979: buffer->nlines = f->nlines;
980:
981: /* Write the structure. */
982: addr = next_address;
983: fwrite (buffer, 1, size, symfile);
984: next_address += size;
985:
986: /* Tell assembler where to write the real line-number data. */
987: fprintf (asmfile, "\t.gdblinetab %d,%d\n",
988: f->filenum, addr + sizeof (int));
989:
990: return addr;
991: }
992:
993: /* Output the `struct sourcevector' which describes all the
994: source files and points a `struct source' for each one. */
995:
996: static int
997: symout_sources ()
998: {
999: register struct gdbfile *f;
1000: int nfiles = 0;
1001: struct sourcevector *s;
1002: int i;
1003: int size;
1004: int addr;
1005:
1006: /* Count number of files to determine size of the sourcevector. */
1007: for (f = gdbfiles; f; f = f->next)
1008: ++nfiles;
1009:
1010: /* Allocate buffer for the sourcevector and record its length. */
1011: size = sizeof (int) + nfiles * sizeof (struct source *);
1012: s = (struct sourcevector *) alloca (size);
1013: s->length = nfiles;
1014:
1015: /* Output a `struct source' for each file; put address into sourcevector. */
1016: for (f = gdbfiles, i = 0; f; f = f->next, i++)
1017: s->source[i] = (struct source *) symout_source_file (f);
1018:
1019: /* Output the sourcevector. */
1020: addr = next_address;
1021: fwrite (s, 1, size, symfile);
1022: next_address += size;
1023: return addr;
1024: }
1025:
1026: /* Call here at the end of compilation, after outputting all the
1027: blocks and symbols, to output the blockvector and typevector
1028: and close the symbol table file. FILETIME is source file's
1029: creation time. */
1030:
1031: void
1032: symout_finish (filename, filetime)
1033: char *filename;
1034: int filetime;
1035: {
1036: int *blockvector = (int *) alloca ((total_blocks + 1) * sizeof (int));
1037: int *typevector = (int *) alloca ((total_types + 1) * sizeof (int));
1038: int now = time (0);
1039: register int i;
1040: struct symbol_root buffer;
1041: char dir[MAXNAMLEN];
1042:
1043: buffer.language = language_c;
1044: buffer.blockvector = (struct blockvector *) next_address;
1045:
1046: /* The two blocks at the beginning of the chain
1047: are the file's private symbols block and public symbols block.
1048: They belong at the front of the blockvector, in that order. */
1049: blockvector[2] = blockvec->address;
1050: blockvec = blockvec->next;
1051: blockvector[1] = blockvec->address;
1052: blockvec = blockvec->next;
1053:
1054: /* The rest of the blocks are in the chain in reverse order. */
1055: for (i = total_blocks; i > 2; i--)
1056: {
1057: blockvector[i] = blockvec->address;
1058: blockvec = blockvec->next;
1059: }
1060: blockvector[0] = total_blocks;
1061:
1062: fwrite (blockvector, sizeof (int), total_blocks + 1, symfile);
1063: next_address += sizeof (int) * (total_blocks + 1);
1064:
1065: buffer.typevector = (struct typevector *) next_address;
1066:
1067: for (i = total_types; i > 0; i--)
1068: {
1069: typevector[i] = typevec->address;
1070: typevec = typevec->next;
1071: }
1072: typevector[0] = total_types;
1073:
1074: fwrite (typevector, sizeof (int), total_types + 1, symfile);
1075: next_address += sizeof (int) * (total_types + 1);
1076:
1077: buffer.sourcevector = (struct sourcevector *) symout_sources ();
1078:
1079: buffer.format = 1;
1080: buffer.textrel = 0; /* These four will be set up by linker. */
1081: buffer.datarel = 0; /* Make them 0 now, which is right for */
1082: buffer.bssrel = 0; /* looking at the .o file in gdb. */
1083: buffer.ldsymoff = 0;
1084:
1085: buffer.version = (char *) next_address;
1086: symout_strings (ctime (&filetime), 0, 0, 0);
1087:
1088: buffer.compilation = (char *) next_address;
1089: symout_strings (ctime (&now), 0, 0, 0);
1090:
1091: buffer.filename = (char *) next_address;
1092: symout_strings (filename, 0, 0, 0);
1093:
1094: buffer.filedir = (char *) next_address;
1095: #ifdef USG
1096: strcpy (dir, getcwd (dir, MAXNAMLEN));
1097: #else
1098: #ifndef VMS
1099: getwd (dir);
1100: #else
1101: abort ();
1102: #endif
1103: #endif
1104: symout_strings (dir, 0, 0, 0);
1105:
1106: fflush (symfile);
1107:
1108: if (ferror (symfile) != 0)
1109: fatal_io_error (symfile_name);
1110:
1111: buffer.length = next_address;
1112:
1113: if (lseek (fileno (symfile), 0, 0) < 0)
1114: pfatal_with_name (symfile_name);
1115: if (write (fileno (symfile), &buffer, sizeof buffer) < 0)
1116: pfatal_with_name (symfile_name);
1117: close (fileno (symfile));
1118: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.