Annotation of researchv10dc/cmd/gcc/symout.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.