diff options
Diffstat (limited to 'gdb/dbxread.c')
-rw-r--r-- | gdb/dbxread.c | 817 |
1 files changed, 779 insertions, 38 deletions
diff --git a/gdb/dbxread.c b/gdb/dbxread.c index 007e7682e0..c1c4acc5c9 100644 --- a/gdb/dbxread.c +++ b/gdb/dbxread.c @@ -1,5 +1,6 @@ /* Read dbx symbol tables and convert to internal format, for GDB. - Copyright (C) 1986, 1987 Free Software Foundation, Inc. + Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc. + Hacked by Michael Tiemann (tiemann@mcc.com) GDB is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone @@ -46,7 +47,12 @@ static struct symbol *define_symbol (); static void start_subfile (); static int hashname (); static void hash_symsegs (); + extern struct symtab *read_symsegs (); +extern void free_all_symtabs (); + +/* C++ */ +static struct type **read_args (); START_FILE @@ -468,6 +474,7 @@ dbx_alloc_type (typenums) type = (struct type *) obstack_alloc (symbol_obstack, sizeof (struct type)); bzero (type, sizeof (struct type)); + TYPE_VPTR_FIELDNO (type) = -1; *type_addr = type; } return type; @@ -682,6 +689,8 @@ start_symtab (name, start_addr) if (s->ldsymoff == symnum * sizeof (struct nlist)) break; current_symseg = s; + if (s != 0) + return; type_vector_length = 160; type_vector = (struct typevector *) xmalloc (sizeof (struct typevector) + type_vector_length * sizeof (struct type *)); @@ -767,6 +776,13 @@ end_symtab (end_addr) register struct linetable *lv; struct subfile *nextsub; + if (current_symseg != 0) + { + last_source_file = 0; + current_symseg = 0; + return; + } + /* Finish the lexical context of the last function in the file. */ if (context_stack) @@ -779,12 +795,10 @@ end_symtab (end_addr) } /* Finish defining all the blocks of this symtab. */ - if (current_symseg == 0) - { - finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr); - finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr); - blockvector = make_blockvector (); - } + finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr); + finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr); + blockvector = make_blockvector (); + current_subfile->line_vector_index = line_vector_index; /* Now create the symtab objects proper, one for each subfile. */ @@ -793,22 +807,16 @@ end_symtab (end_addr) for (subfile = subfiles; subfile; subfile = nextsub) { symtab = (struct symtab *) xmalloc (sizeof (struct symtab)); + symtab->free_ptr = 0; + /* Fill in its components. */ - if (current_symseg) - { - bcopy (current_symseg, symtab, sizeof (struct symtab)); - symtab->free_code = free_linetable; - symtab->free_ptr = 0; - } - else - { - symtab->blockvector = blockvector; - type_vector->length = type_vector_length; - symtab->typevector = type_vector; - symtab->free_code = free_linetable; - if (subfile->next == 0) - symtab->free_ptr = (char *) type_vector; - } + symtab->blockvector = blockvector; + type_vector->length = type_vector_length; + symtab->typevector = type_vector; + symtab->free_code = free_linetable; + if (subfile->next == 0) + symtab->free_ptr = (char *) type_vector; + symtab->filename = subfile->name; lv = subfile->line_vector; lv->nitems = subfile->line_vector_index; @@ -1049,6 +1057,7 @@ symbol_file_command (name) register int val; extern void close (); struct cleanup *old_chain; + struct symtab *symseg; dont_repeat (); @@ -1094,6 +1103,9 @@ symbol_file_command (name) return; } + printf ("Reading symbol data from %s...", name); + fflush (stdout); + /* Now read the string table, all at once. */ val = lseek (desc, N_SYMOFF (hdr) + hdr.a_syms, 0); if (val < 0) @@ -1102,15 +1114,52 @@ symbol_file_command (name) if (val < 0) perror_with_name (name); stringtab = (char *) alloca (buffer); + if (stringtab == NULL) + { + free_all_symtabs (); + printf("%s: symbol table too large for alloca: %d bytes.\n", name, + buffer); + fflush (stdout); + return; + } bcopy (&buffer, stringtab, sizeof buffer); val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer); if (val < 0) perror_with_name (name); + /* Throw away the old symbol table. */ + + free_all_symtabs (); + #ifdef READ_GDB_SYMSEGS /* That puts us at the symsegs. Read them. */ symseg_chain = read_symsegs (desc, name); hash_symsegs (); + + /* Free the symtabs made by read_symsegs, but not their contents, + which have been copied into symtabs on symtab_list. */ + for (symseg = symseg_chain; symseg; symseg = symseg->next) + { + int i; + struct sourcevector *sv = (struct sourcevector *) symseg->linetable; + + for (i = 0; i < sv->length; i++) + { + int j; + struct source *source = sv->source[i]; + struct symtab *sp1 + = (struct symtab *) xmalloc (sizeof (struct symtab)); + + bcopy (symseg, sp1, sizeof (struct symtab)); + sp1->filename = savestring (source->name, strlen (source->name)); + sp1->linetable = &source->contents; + sp1->free_code = free_nothing; + sp1->free_ptr = (i == 0) ? (char *) symseg : 0; + + sp1->next = symtab_list; + symtab_list = sp1; + } + } #else /* Where people are using the 4.2 ld program, must not check for symsegs, because that ld puts randonm garbage at the end of @@ -1123,13 +1172,6 @@ symbol_file_command (name) if (val < 0) perror_with_name (name); - printf ("Reading symbol data from %s...", name); - fflush (stdout); - - /* Throw away the old symbol table. */ - - free_all_symtabs (); - init_misc_functions (); make_cleanup (discard_misc_bunches, 0); init_header_files (); @@ -1199,11 +1241,13 @@ read_dbx_symtab (desc, stringtab, nlistlen) register struct symbol *sym, *prev; int hash; int num_object_files = 0; + struct cleanup *old_chain; #ifdef N_BINCL subfile_stack = 0; #endif + old_chain = make_cleanup (free_all_symtabs, 0); nlist_stream_global = stream; nlist_size_global = nlistlen; stringtab_global = stringtab; @@ -1212,6 +1256,7 @@ read_dbx_symtab (desc, stringtab, nlistlen) for (symnum = 0; symnum < nlistlen; symnum++) { + QUIT; /* allow this to be interruptable */ fread (&buf, sizeof buf, 1, stream); namestring = buf.n_un.n_strx ? buf.n_un.n_strx + stringtab : ""; if (buf.n_type & N_STAB) @@ -1303,6 +1348,7 @@ read_dbx_symtab (desc, stringtab, nlistlen) end_symtab (end_of_text_addr); fclose (stream); + discard_cleanups (old_chain); } /* dbx allows the text of a symbol name to be continued into the @@ -1517,6 +1563,317 @@ process_one_symbol (type, desc, value, name) } } +/************************ READ_ADDL_SYM() ***********************************/ + +static void +read_addl_syms (desc, stringtab, nlistlen, text_addr, text_size) + int desc; + register char *stringtab; + register int nlistlen; + unsigned text_addr; + int text_size; +{ + FILE *stream = fdopen (desc, "r"); + struct nlist buf; + register char *namestring; + register struct symbol *sym, *prev; + int hash; + int num_object_files = 0; + +#ifdef N_BINCL + subfile_stack = 0; +#endif + + nlist_stream_global = stream; + nlist_size_global = nlistlen; + stringtab_global = stringtab; + last_source_file = 0; + bzero (global_sym_chain, sizeof global_sym_chain); + + for (symnum = 0; symnum < nlistlen; symnum++) + { + unsigned type; + + fread (&buf, sizeof buf, 1, stream); + + type = buf.n_type & N_TYPE; + if( (type == N_TEXT) || (type == N_DATA) || (type == N_BSS) ) + { + buf.n_value += text_addr; + } /* Right?? ###### */ + + + namestring = buf.n_un.n_strx ? buf.n_un.n_strx + stringtab : ""; + if (buf.n_type & N_STAB) + process_one_symbol (buf.n_type, buf.n_desc, + buf.n_value, namestring); + /* A static text symbol whose name ends in ".o" + can only mean the start of another object file. + So end the symtab of the source file we have been processing. + This is how we avoid counting the libraries as part + or the last source file. + Also this way we find end of first object file (crt0). */ + else if (buf.n_type == N_TEXT + && !strcmp (namestring + strlen (namestring) - 2, ".o")) + { + if (num_object_files++ == 1) + first_object_file_end = buf.n_value; + if (last_source_file) + { + end_symtab (buf.n_value); /* All this not used##### */ + } + } + else if (buf.n_type & N_EXT || buf.n_type == N_TEXT) + { + int used_up = 0; + + /* Record the location of _etext. */ + if (buf.n_type == (N_TEXT | N_EXT) + && !strcmp (namestring, "_etext")) + { + end_of_text_addr = buf.n_value; + } + + /* Global symbol: see if we came across a dbx definition + for a corresponding symbol. If so, store the value. + Remove syms from the chain when their values are stored, + but search the whole chain, as there may be several syms + from different files with the same name. */ + if (buf.n_type & N_EXT) + { + prev = 0; +#ifdef NAMES_HAVE_UNDERSCORE + hash = hashname (namestring + 1); +#else /* not NAMES_HAVE_UNDERSCORE */ + hash = hashname (namestring); +#endif /* not NAMES_HAVE_UNDERSCORE */ + for (sym = global_sym_chain[hash]; + sym;) + { + if ( +#ifdef NAMES_HAVE_UNDERSCORE + *namestring == '_' + && namestring[1] == SYMBOL_NAME (sym)[0] + && + !strcmp (namestring + 2, SYMBOL_NAME (sym) + 1) +#else /* NAMES_HAVE_UNDERSCORE */ + namestring[0] == SYMBOL_NAME (sym)[0] + && + !strcmp (namestring + 1, SYMBOL_NAME (sym) + 1) +#endif /* NAMES_HAVE_UNDERSCORE */ + ) + { + if (prev) + SYMBOL_VALUE (prev) = SYMBOL_VALUE (sym); + else + global_sym_chain[hash] + = (struct symbol *) SYMBOL_VALUE (sym); + SYMBOL_VALUE (sym) = buf.n_value; + if (prev) + sym = (struct symbol *) SYMBOL_VALUE (prev); + else + sym = global_sym_chain[hash]; + + used_up = 1; + } + else + { + prev = sym; + sym = (struct symbol *) SYMBOL_VALUE (sym); + } + } + } + + /* Defined global or text symbol: record as a misc function + if it didn't give its address to a debugger symbol above. */ + if (buf.n_type <= (N_TYPE | N_EXT) + && buf.n_type != N_EXT + && ! used_up) + record_misc_function (namestring, buf.n_value); + } + } + + if (last_source_file) + { + end_symtab (text_addr + text_size); + } + + fclose (stream); +} + +/***************************** CONDENSE_ADDL_MISC_BUNCHES *******************/ + +static void +condense_addl_misc_bunches () +{ + register int i, j; + register struct misc_bunch *bunch; +#ifdef NAMES_HAVE_UNDERSCORE + int offset = 1; +#else + int offset = 0; +#endif + + misc_function_vector + = (struct misc_function *) xrealloc (misc_function_vector, + (misc_count + misc_function_count) * sizeof (struct misc_function)); + + j = misc_function_count; + bunch = misc_bunch; + while (bunch) + { + for (i = 0; i < misc_bunch_index; i++) + { + misc_function_vector[j] = bunch->contents[i]; + misc_function_vector[j].name + = concat (misc_function_vector[j].name + + (misc_function_vector[j].name[0] == '_' ? offset : 0), + "", ""); + j++; + } + bunch = bunch->next; + misc_bunch_index = MISC_BUNCH_SIZE; + } + + misc_function_count += misc_count; + + /* Sort the misc functions by address. */ + + qsort (misc_function_vector, misc_function_count, + sizeof (struct misc_function), compare_misc_functions); +} + +/**************************** ADD_FILE_COMMAND() ****************************/ +/* This function allows the addition of incrementally linked object files. + Useful for debugging `sun_kick'. */ + +void +add_file_command (arg_string) + char* arg_string; +{ + register int desc; + struct exec hdr; + struct nlist *nlist; + char *stringtab; + long buffer; + register int val; + extern void close (); + struct cleanup *old_chain; + char* name; + unsigned text_addr; + + for( ; *arg_string == ' '; arg_string++ ); + name = arg_string; + for( ; *arg_string != ' ' ; arg_string++ ); + *arg_string++ = (char) 0; + for( ; *arg_string == ' '; arg_string++ ); + text_addr = (unsigned) atoi(arg_string); + + printf("filename \"%s\", and text_addr = 0x%x\n", name, text_addr ); + + dont_repeat (); + + if (name == 0) + { + if (symtab_list && !query ("Discard symbol table? ", 0)) + error ("Not confirmed."); + free_all_symtabs (); + return; + } + + /* if (symtab_list && !query ("Add new symbols from \"%s\"? ", name)) + error ("Not confirmed."); + */ + { + char *absolute_name; + desc = openp (getenv ("PATH"), 1, name, O_RDONLY, 0, &absolute_name); + if (desc < 0) + perror_with_name (name); + else + name = absolute_name; + } + + old_chain = make_cleanup (close, desc); + make_cleanup (free_current_contents, &name); + + val = myread (desc, &hdr, sizeof hdr); + if (val < 0) + perror_with_name (name); + + if (N_BADMAG (hdr)) + error ("File \"%s\" has a bad header.", name); + + if (hdr.a_syms == 0) + { + printf ("%s does not have a symbol-table.\n", name); + fflush (stdout); + return; + } + + /* Now read the string table, all at once. */ + val = lseek (desc, N_SYMOFF (hdr) + hdr.a_syms, 0); + if (val < 0) + perror_with_name (name); + val = myread (desc, &buffer, sizeof buffer); + if (val < 0) + perror_with_name (name); + stringtab = (char *) alloca (buffer); + bcopy (&buffer, stringtab, sizeof buffer); + val = myread (desc, stringtab + sizeof buffer, buffer - sizeof buffer); + if (val < 0) + perror_with_name (name); + + /* That puts us at the symsegs. Read them. ########## Also need other + changes if they exist. */ + + + /* Position to read the symbol table. Do not read it all at once. */ + val = lseek (desc, N_SYMOFF (hdr), 0); + if (val < 0) + perror_with_name (name); + + printf ("Reading symbol data from %s...", name); + fflush (stdout); + + init_misc_functions (); + make_cleanup (discard_misc_bunches, 0); + init_header_files (); + make_cleanup (free_header_files, 0); + + read_addl_syms (desc, stringtab, hdr.a_syms / sizeof(struct nlist) + ,text_addr, hdr.a_text) ; + + /* Sort symbols alphabetically within each block. */ + + sort_syms (); + + /* Go over the all misc functions and install them in vector. */ + + condense_addl_misc_bunches (); + + /* Don't allow char * to have a typename (else would get caddr_t.) */ + + TYPE_NAME (lookup_pointer_type (builtin_type_char)) = 0; + + /* Make a default for file to list. */ + + select_source_symtab (symtab_list); + + do_cleanups (old_chain); + + /* Free the symtabs made by read_symsegs, but not their contents, + which have been copied into symtabs on symtab_list. */ + while (symseg_chain) + { + register struct symtab *s = symseg_chain->next; + free (symseg_chain); + symseg_chain = s; + } + + printf ("done.\n"); + fflush (stdout); +} + static struct symbol * define_symbol (value, string, desc) int value; @@ -1668,6 +2025,16 @@ define_symbol (value, string, desc) if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0 && (TYPE_FLAGS (SYMBOL_TYPE (sym)) & TYPE_FLAG_PERM) == 0) TYPE_NAME (SYMBOL_TYPE (sym)) = concat (SYMBOL_NAME (sym), "", ""); + /* C++ vagaries: we may have a type which is derived from + a base type which did not have its name defined when the + derived class was output. We fill in the derived class's + base part member's name here in that case. */ + else if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT + || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION) + && TYPE_BASECLASS (SYMBOL_TYPE (sym)) + && TYPE_FIELD_NAME (SYMBOL_TYPE (sym), 0) == 0) + TYPE_FIELD_NAME (SYMBOL_TYPE (sym), 0) = TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym))); + add_symbol_to_list (sym, &file_symbols); break; @@ -1771,6 +2138,10 @@ read_type (pp) break; } /* Skip the name the cross-ref points to. */ + /* Note: for C++, the cross reference may be to a base type which + has not yet been seen. In this case, we skip to the comma, + which will mark the end of the base class name. (The ':' + at the end of the base class name will be skipped as well.) */ *pp = (char *) index (*pp, ','); /* Just allocate the type and leave it zero if nothing known */ return dbx_alloc_type (typenums); @@ -1799,6 +2170,27 @@ read_type (pp) smash_to_pointer_type (type, read_type (pp)); break; + case '@': + { + struct type *domain = read_type (pp); + char c; + struct type *ptrtype; + + if (*(*pp)++ != ',') + error ("invalid member pointer data format, at symtab pos %d.", + symnum); + + ptrtype = read_type (pp); + type = dbx_alloc_type (typenums); + smash_to_member_pointer_type (type, domain, ptrtype); + } + break; + + case '&': + type = dbx_alloc_type (typenums); + smash_to_reference_type (type, read_type (pp)); + break; + case 'f': type = dbx_alloc_type (typenums); smash_to_function_type (type, read_type (pp)); @@ -1892,9 +2284,23 @@ read_struct_type (pp, type) struct nextfield { struct nextfield *next; + int visibility; struct field field; }; + struct next_fnfield + { + struct next_fnfield *next; + int visibility; + struct fn_field fn_field; + }; + + struct next_fnfieldlist + { + struct next_fnfieldlist *next; + struct fn_fieldlist fn_fieldlist; + }; + register struct nextfield *list = 0; struct nextfield *new; int totalsize; @@ -1903,20 +2309,72 @@ read_struct_type (pp, type) int nfields = 0; register int n; + register struct next_fnfieldlist *mainlist = 0; + int nfn_fields = 0; + struct type *baseclass = NULL; + int read_possible_virtual_info = 0; + TYPE_CODE (type) = TYPE_CODE_STRUCT; /* First comes the total size in bytes. */ TYPE_LENGTH (type) = read_number (pp, 0); - /* Now come the fields, as NAME:TYPENUM,BITPOS,BITSIZE; for each one. - At the end, we see a semicolon instead of a field. */ + /* C++: Now, if the class is a derived class, then the next character + will be a '!', followed by the type of the base class. Allocate + pretend that that base class is a sub-structure of this one, + with its field name being the type name of the derived class. This + cannot cause a naming conflict, since field names cannot be + type names. This will magically recurse itself to gound terms + when all is read and done. */ + if (**pp == '!') + { + *pp += 1; + + switch (*(*pp)++) + { + case '0': + break; + case '1': + TYPE_VIA_PROTECTED (type) = 1; + break; + case '2': + TYPE_VIA_PUBLIC (type) = 1; + break; + default: + error ("Invalid symbol data: bad visibility format at symtab pos %d.", + symnum); + } + + if (**pp == '\\') *pp = next_symbol_text (); + new = (struct nextfield *) alloca (sizeof (struct nextfield)); + new->next = list; + list = new; + + baseclass = read_type (pp); + list->field.type = baseclass; + list->field.name = TYPE_NAME (baseclass); + *pp += 1; /* skip ',' */ + list->field.bitpos = 0; + list->field.bitsize = 0; /* this should be an unpacked field! */ + nfields++; + } + + /* Now come the fields, as NAME:?TYPENUM,BITPOS,BITSIZE; for each one. + At the end, we see a semicolon instead of a field. + + In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for + a static field. + + The `?' is a placeholder for one of '+' (public visibility), + '0' (protected visibility), and '-' (private visibility). */ while (**pp != ';') { + int visibility; + /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') - *pp = next_symbol_text (); + if (**pp == '\\') *pp = next_symbol_text (); /* Get space to record the next field's data. */ new = (struct nextfield *) alloca (sizeof (struct nextfield)); @@ -1927,9 +2385,48 @@ read_struct_type (pp, type) p = *pp; while (*p != ':') p++; list->field.name = savestring (*pp, p - *pp); + + /* Check to see if we have hit the methods yet. */ + if (p[1] == ':') + break; + *pp = p + 1; + + /* This means we have a visibility for a field coming. */ + if (**pp == '/') + { + switch (*++*pp) + { + case '0': + visibility = 0; + *pp += 1; + break; + + case '1': + visibility = 1; + *pp += 1; + break; + + case '2': + visibility = 2; + *pp += 1; + break; + } + } + /* else normal dbx-style format. */ + list->field.type = read_type (pp); - if (**pp != ',') + if (**pp == ':') + { + list->field.bitpos = (long)-1; + p = ++(*pp); + while (*p != ';') p++; + list->field.bitsize = (long) savestring (*pp, p - *pp); + *pp = p + 1; + nfields++; + continue; + } + else if (**pp != ',') error ("Invalid symbol data: bad structure-type format at symtab pos %d.", symnum); (*pp)++; /* Skip the comma. */ @@ -1950,18 +2447,218 @@ read_struct_type (pp, type) nfields++; } - (*pp)++; /* Skip the terminating ';'. */ + /* Now come the method fields, as NAME::methods + where each method is of the form TYPENUM,ARGS,...:PHYSNAME; + At the end, we see a semicolon instead of a field. + + For the case of overloaded operators, the format is + OPERATOR::*.methods, where OPERATOR is the string "operator", + `*' holds the place for an operator name (such as `+=') + and `.' marks the end of the operator name. */ + if (p[1] == ':') + { + /* Now, read in the methods. To simplify matters, we + "unread" the name that has been read, so that we can + start from the top. */ + + p = *pp; + + /* chill the list of fields: the last entry (at the head) + is a partially constructed entry which we now scrub. */ + list = list->next; + + /* For each list of method lists... */ + do + { + int i; + struct next_fnfield *sublist = 0; + struct fn_field *fn_fields = 0; + int length = 0; + struct next_fnfieldlist *new_mainlist = + (struct next_fnfieldlist *)alloca (sizeof (struct next_fnfieldlist)); + + /* read in the name. */ + while (*p != ':') p++; + if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && (*pp)[2] == '$') + { + static char opname[32] = "operator "; + char *o = opname + 9; + + /* Skip past '::'. */ + p += 2; + while (*p != '.') + *o++ = *p++; + new_mainlist->fn_fieldlist.name = savestring (opname, o - opname); + /* Skip past '.' */ + *pp = p + 1; + } + else + { + i = 0; + new_mainlist->fn_fieldlist.name = savestring (*pp, p - *pp); + /* Skip past '::'. */ + *pp = p + 2; + } + + do + { + struct next_fnfield *new_sublist = + (struct next_fnfield *)alloca (sizeof (struct next_fnfield)); + + /* Check for and handle cretinous dbx symbol name continuation! */ + if (**pp == '\\') *pp = next_symbol_text (); + + new_sublist->fn_field.type = read_type (pp); + new_sublist->fn_field.args = read_args (pp, ':'); + p = *pp; + while (*p != ';') p++; + new_sublist->fn_field.physname = savestring (*pp, p - *pp); + *pp = p + 1; + new_sublist->visibility = *(*pp)++ - '0'; + if (**pp == '\\') *pp = next_symbol_text (); + + if (*(*pp)++ == '*') + new_sublist->fn_field.voffset = read_number (pp, ';') + 1; + else + new_sublist->fn_field.voffset = 0; + + new_sublist->next = sublist; + sublist = new_sublist; + length++; + } + while (**pp != ';'); + + *pp += 1; + + new_mainlist->fn_fieldlist.fn_fields = + (struct fn_field *) obstack_alloc (symbol_obstack, + sizeof (struct fn_field) * length); + TYPE_FN_PRIVATE_BITS (new_mainlist->fn_fieldlist) = + (int *) obstack_alloc (symbol_obstack, + sizeof (int) * (1 + (length >> 5))); + + TYPE_FN_PROTECTED_BITS (new_mainlist->fn_fieldlist) = + (int *) obstack_alloc (symbol_obstack, + sizeof (int) * (1 + (length >> 5))); + + for (i = length; sublist; sublist = sublist->next) + { + new_mainlist->fn_fieldlist.fn_fields[--i] = sublist->fn_field; + if (sublist->visibility == 0) + B_SET (new_mainlist->fn_fieldlist.private_fn_field_bits, i); + else if (sublist->visibility == 1) + B_SET (new_mainlist->fn_fieldlist.protected_fn_field_bits, i); + } + + new_mainlist->fn_fieldlist.length = length; + new_mainlist->next = mainlist; + mainlist = new_mainlist; + nfn_fields++; + } + while (**pp != ';'); + + *pp += 2; + + if (**pp == '~') + { + read_possible_virtual_info = 1; + *pp += 1; + } + if (**pp == '-') + { + TYPE_HAS_DESTRUCTOR (type) = 1; + TYPE_HAS_CONSTRUCTOR (type) = 1; + *pp += 1; + } + else if (**pp == '+') + { + TYPE_HAS_CONSTRUCTOR (type) = 1; + *pp += 1; + } + } + else *pp += 1; /* Now create the vector of fields, and record how big it is. */ TYPE_NFIELDS (type) = nfields; TYPE_FIELDS (type) = (struct field *) obstack_alloc (symbol_obstack, sizeof (struct field) * nfields); + TYPE_FIELD_PRIVATE_BITS (type) = + (int *) obstack_alloc (symbol_obstack, + sizeof (int) * (1 + (nfields >> 5))); + TYPE_FIELD_PROTECTED_BITS (type) = + (int *) obstack_alloc (symbol_obstack, + sizeof (int) * (1 + (nfields >> 5))); + + TYPE_NFN_FIELDS (type) = nfn_fields; + TYPE_NFN_FIELDS_TOTAL (type) = nfn_fields; + if (baseclass) + TYPE_NFN_FIELDS_TOTAL (type) += TYPE_NFN_FIELDS_TOTAL (baseclass); + + TYPE_FN_FIELDLISTS (type) = + (struct fn_fieldlist *) obstack_alloc (symbol_obstack, + sizeof (struct fn_fieldlist) * nfn_fields); /* Copy the saved-up fields into the field vector. */ for (n = nfields; list; list = list->next) - TYPE_FIELD (type, --n) = list->field; + { + TYPE_FIELD (type, --n) = list->field; + if (list->visibility == 0) + SET_TYPE_FIELD_PRIVATE (type, n); + else if (list->visibility == 1) + SET_TYPE_FIELD_PROTECTED (type, n); + } + + for (n = nfn_fields; mainlist; mainlist = mainlist->next) + TYPE_FN_FIELDLISTS (type)[--n] = mainlist->fn_fieldlist; + + TYPE_BASECLASS (type) = baseclass; + + if (read_possible_virtual_info) + { + /* Read either a '%' or the final ';'. */ + if (*(*pp)++ == '%') + { + /* Now we must record the virtual function table pointer's + field information. */ + + struct type *t; + int i; + + t = read_type (pp); + p = (*pp)++; + while (*p != ';') p++; + TYPE_VPTR_BASETYPE (type) = t; + if (type == t) + { + if (TYPE_FIELD_NAME (t, 0) == 0) + TYPE_VPTR_FIELDNO (type) = i = 0; + else for (i = TYPE_NFIELDS (t) - 1; i >= 0; --i) + if (! strncmp (TYPE_FIELD_NAME (t, i), *pp, + strlen (TYPE_FIELD_NAME (t, i)))) + { + TYPE_VPTR_FIELDNO (type) = i; + break; + } + if (i < 0) + error ("virtual function table field not found"); + } + else + TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type)); + *pp = p; + } + else + { + TYPE_VPTR_BASETYPE (type) = 0; + TYPE_VPTR_FIELDNO (type) = -1; + } + } + else + { + TYPE_VPTR_BASETYPE (type) = 0; + TYPE_VPTR_FIELDNO (type) = -1; + } return type; } @@ -1995,8 +2692,7 @@ read_enum_type (pp, type) while (**pp && **pp != ';') { /* Check for and handle cretinous dbx symbol name continuation! */ - if (**pp == '\\') - *pp = next_symbol_text (); + if (**pp == '\\') *pp = next_symbol_text (); p = *pp; while (*p != ':') p++; @@ -2169,6 +2865,48 @@ read_number (pp, end) return n * sign; } +/* Read in an argument list. This is a list of types. It is terminated with + a ':', FYI. Return the list of types read in. */ +static struct type ** +read_args (pp, end) + char **pp; + int end; +{ + struct type *types[1024], **rval; /* allow for fns of 1023 parameters */ + int n = 0; + + while (**pp != end) + { + if (**pp != ',') + error ("Invalid argument list: no ',', at symtab pos %d", symnum); + *pp += 1; + types[n++] = read_type (pp); + } + *pp += 1; /* get past `end' (the ':' character) */ + + if (n == 1) + { + rval = (struct type **) xmalloc (2 * sizeof (struct type *)); + } + else + { + rval = (struct type **) xmalloc (n * sizeof (struct type *)); + } + bcopy (types, rval, n * sizeof (struct type *)); + return rval; +} + +/* This function is really horrible, but to avoid it, there would need + to be more filling in of forward references. */ +int +fill_in_vptr_fieldno (type) + struct type *type; +{ + if (TYPE_VPTR_FIELDNO (type) < 0) + TYPE_VPTR_FIELDNO (type) = fill_in_vptr_fieldno (TYPE_BASECLASS (type)); + return TYPE_VPTR_FIELDNO (type); +} + static initialize () { @@ -2176,6 +2914,9 @@ initialize () add_com ("symbol-file", class_files, symbol_file_command, "Load symbol table (in dbx format) from executable file FILE."); + + add_com ("add-file", class_files, add_file_command, + "Load the symbols from FILE, assuming its codes is at TEXT_START.") ; } END_FILE |