aboutsummaryrefslogtreecommitdiff
path: root/gdb/dbxread.c
diff options
context:
space:
mode:
authorgdb-2.5.1 <gdb@fsf.org>1988-05-02 01:00:00 +0100
committerPedro Alves <palves@redhat.com>2012-06-03 15:36:30 +0100
commit632ea0ccc5c4c3f9fc06881bfedfc4b075873941 (patch)
tree96f152433c41c5f51fe57307b287eb85865a43e2 /gdb/dbxread.c
parent7b4ac7e1ed2c4616bce56d1760807798be87ac9e (diff)
downloadgdb-632ea0ccc5c4c3f9fc06881bfedfc4b075873941.zip
gdb-632ea0ccc5c4c3f9fc06881bfedfc4b075873941.tar.gz
gdb-632ea0ccc5c4c3f9fc06881bfedfc4b075873941.tar.bz2
gdb-2.5.1
Diffstat (limited to 'gdb/dbxread.c')
-rw-r--r--gdb/dbxread.c817
1 files changed, 779 insertions, 38 deletions
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index 007e768..c1c4acc 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