aboutsummaryrefslogtreecommitdiff
path: root/gdb/dbxread.c
diff options
context:
space:
mode:
authorgdb-2.8.1 <gdb@fsf.org>1988-12-16 00:00:00 +0000
committerPedro Alves <palves@redhat.com>2012-06-03 15:36:31 +0100
commitbb7592f01006b09c846831a9fb9c306307ba34f6 (patch)
tree83e99233f937d7a06eee7c627543288feb125929 /gdb/dbxread.c
parent3bf57d210832b28e9361990830eb722a619f031b (diff)
downloadgdb-bb7592f01006b09c846831a9fb9c306307ba34f6.zip
gdb-bb7592f01006b09c846831a9fb9c306307ba34f6.tar.gz
gdb-bb7592f01006b09c846831a9fb9c306307ba34f6.tar.bz2
gdb-2.8.1
Diffstat (limited to 'gdb/dbxread.c')
-rw-r--r--gdb/dbxread.c775
1 files changed, 763 insertions, 12 deletions
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index 0ac4ff8..27ffcc1 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, 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
@@ -51,6 +52,9 @@ static void hash_symsegs ();
extern struct symtab *read_symsegs ();
extern void free_all_symtabs ();
+/* C++ */
+static struct type **read_args ();
+
/* Macro for number of symbol table entries (in usual a.out format).
Some machines override this definition. */
#ifndef NUMBER_OF_SYMBOLS
@@ -561,6 +565,8 @@ 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_MAIN_VARIANT (type) = type;
*type_addr = type;
}
return type;
@@ -1197,6 +1203,7 @@ sort_syms ()
if (BLOCK_SHOULD_SORT (b))
qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
sizeof (struct symbol *), compare_symbols);
+#if 0
else
{
int lastindex = BLOCK_NSYMS (b) - 1;
@@ -1209,6 +1216,7 @@ sort_syms ()
BLOCK_SYM (b, lastindex - j) = sym;
}
}
+#endif
}
}
}
@@ -1667,7 +1675,14 @@ process_one_symbol (type, desc, value, name)
if (type == N_ENTRY)
/* This code appears in libraries on Gould machines. */
return;
- error ("Invalid symbol data: does not start by identifying a source file.");
+
+ if (type == N_SLINE && desc == -1)
+ /* This code is used by the Sun4 coimpiler; ignore it. */
+ return;
+
+ /* This should give an aborting error. */
+ printf ("Invalid symbol data: does not start by identifying a source file.\ntype == %d\n\n", type);
+ return;
}
switch (type)
@@ -1678,7 +1693,7 @@ process_one_symbol (type, desc, value, name)
a new function. We must process its "name" normally for dbx,
but also record the start of a new lexical context, and possibly
also the end of the lexical context for the previous function. */
-
+
within_function = 1;
if (context_stack_depth > 0)
{
@@ -1806,6 +1821,316 @@ 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");
+ register char *namestring;
+ register struct symbol *sym, *prev;
+ int hash;
+ int num_object_files = 0;
+
+#ifdef N_BINCL
+ subfile_stack = 0;
+#endif
+
+ last_source_file = 0;
+ bzero (global_sym_chain, sizeof global_sym_chain);
+ symtab_input_desc = desc;
+ stringtab_global = stringtab;
+ fill_symbuf ();
+
+ for (symnum = 0; symnum < nlistlen; symnum++)
+ {
+ struct nlist *bufp;
+ int type;
+
+ QUIT; /* allow this to be interruptable */
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf ();
+ bufp = &symbuf[symbuf_idx++];
+ type = bufp->n_type & N_TYPE;
+ namestring = bufp->n_un.n_strx ? bufp->n_un.n_strx + stringtab : "";
+
+ if( (type == N_TEXT) || (type == N_DATA) || (type == N_BSS) )
+ {
+ /* Relocate this file's symbol table information
+ to the address it has been loaded into. */
+ bufp->n_value += text_addr;
+ }
+
+ type = bufp->n_type;
+
+ if (type & N_STAB)
+ process_one_symbol (type, bufp->n_desc,
+ bufp->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 ((type == N_TEXT
+#ifdef N_NBTEXT
+ || type == N_NBTEXT
+#endif
+ )
+ && (!strcmp (namestring + strlen (namestring) - 2, ".o"))
+ || ! strcmp (namestring, "-l", 2))
+ {
+ if (num_object_files++ == 1)
+ first_object_file_end = bufp->n_value;
+ if (last_source_file)
+ end_symtab (bufp->n_value);
+ }
+ else if (type & N_EXT || type == N_TEXT
+#ifdef N_NBTEXT
+ || type == N_NBTEXT
+#endif
+ )
+ {
+ int used_up = 0;
+
+ /* Record the location of _etext. */
+ if (type == (N_TEXT | N_EXT)
+ && !strcmp (namestring, "_etext"))
+ end_of_text_addr = bufp->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 (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) = bufp->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 (type <= (N_TYPE | N_EXT)
+ && type != N_EXT
+ && ! used_up)
+ record_misc_function (namestring, bufp->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. */
+
+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;
+
+ if (arg_string == 0)
+ error ("add-file takes a file name and an address");
+
+ for( ; *arg_string == ' '; arg_string++ );
+ name = arg_string;
+ for( ; *arg_string && *arg_string != ' ' ; arg_string++ );
+ *arg_string++ = (char) 0;
+
+ if (name[0] == 0)
+ error ("add-file takes a file name and an address");
+
+ text_addr = parse_and_eval_address (arg_string);
+
+ dont_repeat ();
+
+ if (query ("add symbol table from filename \"%s\" at text_addr = 0x%x\n", name, text_addr))
+ {
+ desc = open (name, O_RDONLY);
+ if (desc < 0)
+ perror_with_name (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);
+ }
+ else error ("Not confirmed.");
+}
+
static struct symbol *
define_symbol (value, string, desc)
int value;
@@ -1955,6 +2280,13 @@ define_symbol (value, string, desc)
SYMBOL_TYPE (sym) = builtin_type_unsigned_int;
break;
+ case 'P':
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) = value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
case 'r':
SYMBOL_CLASS (sym) = LOC_REGISTER;
SYMBOL_VALUE (sym) = value;
@@ -1979,6 +2311,20 @@ define_symbol (value, string, desc)
TYPE_NAME (SYMBOL_TYPE (sym)) =
obsavestring (SYMBOL_NAME (sym),
strlen (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_N_BASECLASSES (SYMBOL_TYPE (sym)))
+ {
+ int i;
+ for (i = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)); i > 0; i--)
+ if (TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i-1) == 0)
+ TYPE_FIELD_NAME (SYMBOL_TYPE (sym), i-1) = TYPE_NAME (TYPE_BASECLASS (SYMBOL_TYPE (sym), i));
+ }
+
add_symbol_to_list (sym, &file_symbols);
break;
@@ -2082,7 +2428,11 @@ read_type (pp)
break;
}
/* Skip the name the cross-ref points to. */
- *pp = (char *) index (*pp, ',');
+ /* 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, ':') + 1;
/* Just allocate the type and leave it zero if nothing known */
return dbx_alloc_type (typenums);
@@ -2110,6 +2460,27 @@ read_type (pp)
smash_to_pointer_type (type, read_type (pp));
break;
+ case '@':
+ {
+ struct type *domain = read_type (pp);
+ char c;
+ struct type *memtype;
+
+ if (*(*pp)++ != ',')
+ error ("invalid member type data format, at symtab pos %d.",
+ symnum);
+
+ memtype = read_type (pp);
+ type = dbx_alloc_type (typenums);
+ smash_to_member_type (type, domain, memtype);
+ }
+ 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));
@@ -2203,9 +2574,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;
@@ -2214,20 +2599,95 @@ 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 number of base classes derived from.
+ Each element in the list contains visibility information,
+ the offset of this base class in the derived structure,
+ and then the base type. */
+ if (**pp == '!')
+ {
+ int i, n_baseclasses, offset;
+ struct type **baseclass_vec;
+ struct type *baseclass;
+ int via_public, via_virtual;
+ *pp += 1;
+
+ n_baseclasses = read_number (pp, ',');
+ baseclass_vec = (struct type **)
+ obstack_alloc (symbol_obstack,
+ (n_baseclasses) * sizeof (struct type **)) - 1;
+ for (i = 1; i <= n_baseclasses; i++)
+ {
+ if (**pp == '\\') *pp = next_symbol_text ();
+ switch (*(*pp)++)
+ {
+ case '0':
+ via_virtual = 0;
+ break;
+ case '1':
+ via_virtual = 1;
+ break;
+ default:
+ error ("Invalid symbol data: bad visibility format at symtab pos %d.",
+ symnum);
+ }
+ switch (*(*pp)++)
+ {
+ case '0':
+ via_public = 0;
+ break;
+ case '2':
+ via_public = 1;
+ break;
+ default:
+ error ("Invalid symbol data: bad visibility format at symtab pos %d.",
+ symnum);
+ }
+ offset = read_number (pp, ',');
+ baseclass = read_type (pp);
+ *pp += 1; /* skip trailing ';' */
+ baseclass_vec[i] = lookup_basetype_type (baseclass, offset, via_virtual, via_public);
+
+ /* Make this baseclass visible for structure-printing purposes. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+ list->field.type = baseclass_vec[i];
+ list->field.name = TYPE_NAME (baseclass_vec[i]);
+ list->field.bitpos = offset;
+ list->field.bitsize = 0; /* this should be an unpacked field! */
+ nfields++;
+ }
+ TYPE_N_BASECLASSES (type) = n_baseclasses;
+ TYPE_BASECLASSES (type) = baseclass_vec;
+ }
+
+ /* 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));
@@ -2238,9 +2698,49 @@ read_struct_type (pp, type)
p = *pp;
while (*p != ':') p++;
list->field.name = obsavestring (*pp, p - *pp);
+
+ /* C++: 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 == ':')
+ {
+ /* read a static member. */
+ 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. */
@@ -2262,18 +2762,216 @@ 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 += 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;
+
+ if (**pp == '~')
+ {
+ *pp += 1;
+
+ if (**pp == '=')
+ {
+ TYPE_FLAGS (type)
+ |= TYPE_FLAG_HAS_CONSTRUCTOR | TYPE_FLAG_HAS_DESTRUCTOR;
+ *pp += 1;
+ }
+ else if (**pp == '+')
+ {
+ TYPE_FLAGS (type) |= TYPE_FLAG_HAS_CONSTRUCTOR;
+ *pp += 1;
+ }
+ else if (**pp == '-')
+ {
+ TYPE_FLAGS (type) |= TYPE_FLAG_HAS_DESTRUCTOR;
+ *pp += 1;
+ }
+
+ /* 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, 1));
+ *pp = p + 1;
+ }
+ else
+ {
+ TYPE_VPTR_BASETYPE (type) = 0;
+ TYPE_VPTR_FIELDNO (type) = -1;
+ }
+ }
+ else
+ {
+ TYPE_VPTR_BASETYPE (type) = 0;
+ TYPE_VPTR_FIELDNO (type) = -1;
+ }
return type;
}
@@ -2309,8 +3007,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++;
@@ -2492,6 +3189,57 @@ 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;
+ /* Check for and handle cretinous dbx symbol name continuation! */
+ if (**pp == '\\')
+ *pp = next_symbol_text ();
+
+ types[n++] = read_type (pp);
+ }
+ *pp += 1; /* get past `end' (the ':' character) */
+
+ if (n == 1)
+ {
+ rval = (struct type **) xmalloc (2 * sizeof (struct type *));
+ }
+ else if (TYPE_CODE (types[n-1]) != TYPE_CODE_VOID)
+ {
+ rval = (struct type **) xmalloc ((n + 1) * sizeof (struct type *));
+ bzero (rval + n, 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, 1));
+ return TYPE_VPTR_FIELDNO (type);
+}
+
static
initialize ()
{
@@ -2499,6 +3247,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