Several changes to fix misc problems with enums, structs, and unions,

including building symbol table entries for enumeration members.
This commit is contained in:
Fred Fish
1991-12-06 02:22:10 +00:00
parent a0a6174ae3
commit 715cafcbde
2 changed files with 137 additions and 71 deletions

View File

@ -1,3 +1,14 @@
Thu Dec 5 18:19:43 1991 Fred Fish (fnf at cygnus.com)
* dwarfread.c (enum_type): Build a correct TYPE_NAME, add a
symbol to the symbol table for each member of the enum.
* dwarfread.c (struct_type): Build a correct TYPE_NAME.
* dwarfread.c (add_enum_psymbol): New function to extract enum
member names and add them to the partial symbol table while
building partial symbol tables.
Thu Dec 5 17:31:05 1991 John Gilmore (gnu at cygnus.com) Thu Dec 5 17:31:05 1991 John Gilmore (gnu at cygnus.com)
* symtab.c (check_stub_method): Must allocate two extra argument * symtab.c (check_stub_method): Must allocate two extra argument

View File

@ -1,3 +1,4 @@
/* DWARF debugging format support for GDB. /* DWARF debugging format support for GDB.
Copyright (C) 1991 Free Software Foundation, Inc. Copyright (C) 1991 Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support, portions based on dbxread.c, Written by Fred Fish at Cygnus Support, portions based on dbxread.c,
@ -874,9 +875,10 @@ SYNOPSIS
DESCRIPTION DESCRIPTION
Given pointer to a die information structure for a die which Given pointer to a die information structure for a die which
defines a union or structure, and pointers to the raw die data defines a union or structure (and MUST define one or the other),
that define the range of dies which define the members, compute and pointers to the raw die data that define the range of dies which
and return the user defined type for the structure or union. define the members, compute and return the user defined type for the
structure or union.
*/ */
static struct type * static struct type *
@ -896,8 +898,6 @@ DEFUN(struct_type, (dip, thisdie, enddie, objfile),
int nfields = 0; int nfields = 0;
int n; int n;
char *tpart1; char *tpart1;
char *tpart2;
char *tpart3;
struct dieinfo mbr; struct dieinfo mbr;
char *nextdie; char *nextdie;
@ -905,49 +905,40 @@ DEFUN(struct_type, (dip, thisdie, enddie, objfile),
{ {
type = alloc_utype (dip -> dieref, NULL); type = alloc_utype (dip -> dieref, NULL);
} }
if (dip -> dietag == TAG_structure_type || dip -> dietag == TAG_union_type) TYPE_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *)
obstack_alloc (symbol_obstack, sizeof (struct cplus_struct_type));
(void) memset (TYPE_CPLUS_SPECIFIC (type), 0,
sizeof (struct cplus_struct_type));
switch (dip -> dietag)
{ {
TYPE_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *) case TAG_structure_type:
obstack_alloc (symbol_obstack, sizeof (struct cplus_struct_type)); TYPE_CODE (type) = TYPE_CODE_STRUCT;
(void) memset (TYPE_CPLUS_SPECIFIC (type), 0, tpart1 = "struct";
sizeof (struct cplus_struct_type)); break;
if (dip -> dietag == TAG_structure_type) case TAG_union_type:
{ TYPE_CODE (type) = TYPE_CODE_UNION;
TYPE_CODE (type) = TYPE_CODE_STRUCT; tpart1 = "union";
tpart1 = "struct "; break;
} default:
else /* Should never happen */
{ TYPE_CODE (type) = TYPE_CODE_UNDEF;
TYPE_CODE (type) = TYPE_CODE_UNION; tpart1 = "???";
tpart1 = "union "; SQUAWK (("missing structure or union tag"));
} break;
}
else
{
tpart1 = "";
SQUAWK (("missing structure or union tag"));
TYPE_CODE (type) = TYPE_CODE_UNDEF;
} }
/* Some compilers try to be helpful by inventing "fake" names for anonymous /* Some compilers try to be helpful by inventing "fake" names for anonymous
enums, structures, and unions, like "~0fake". Thanks, but no thanks. */ enums, structures, and unions, like "~0fake" or ".0fake". Thanks, but
if (dip -> at_name == NULL no thanks... */
|| *dip -> at_name == '~' if (dip -> at_name != NULL
|| *dip -> at_name == '.') && *dip -> at_name != '~'
&& *dip -> at_name != '.')
{ {
tpart2 = "{...}"; TYPE_NAME (type) = obconcat (tpart1, " ", dip -> at_name);
} }
else if (dip -> at_byte_size != 0)
{ {
tpart2 = dip -> at_name;
}
if (dip -> at_byte_size == 0)
{
tpart3 = " <opaque>";
} else {
TYPE_LENGTH (type) = dip -> at_byte_size; TYPE_LENGTH (type) = dip -> at_byte_size;
tpart3 = "";
} }
TYPE_NAME (type) = concat (tpart1, tpart2, tpart3, NULL);
thisdie += dip -> dielength; thisdie += dip -> dielength;
while (thisdie < enddie) while (thisdie < enddie)
{ {
@ -1331,14 +1322,18 @@ DESCRIPTION
starts an enumeration, process all the dies that define the members starts an enumeration, process all the dies that define the members
of the enumeration and return a type pointer for the enumeration. of the enumeration and return a type pointer for the enumeration.
At the same time, for each member of the enumeration, create a
symbol for it with namespace VAR_NAMESPACE and class LOC_CONST,
and give it the type of the enumeration itself.
NOTES
Note that the DWARF specification explicitly mandates that enum Note that the DWARF specification explicitly mandates that enum
constants occur in reverse order from the source program order, constants occur in reverse order from the source program order,
for "consistency" and because this ordering is easier for many for "consistency" and because this ordering is easier for many
compilers to generate. (Draft 5, sec 3.9.5, Enumeration type compilers to generate. (Draft 5, sec 3.9.5, Enumeration type
Entries) Entries). Because gdb wants to see the enum members in program
source order, we have to ensure that the order gets reversed while
Because gdb wants to see the enum members in program source
order, we have to ensure that the order gets reversed while
we are processing them. we are processing them.
*/ */
@ -1354,40 +1349,30 @@ DEFUN(enum_type, (dip), struct dieinfo *dip)
struct nextfield *new; struct nextfield *new;
int nfields = 0; int nfields = 0;
int n; int n;
char *tpart1;
char *tpart2;
char *tpart3;
char *scan; char *scan;
char *listend; char *listend;
long ltemp; long ltemp;
short stemp; short stemp;
struct symbol *sym;
if ((type = lookup_utype (dip -> dieref)) == NULL) if ((type = lookup_utype (dip -> dieref)) == NULL)
{ {
type = alloc_utype (dip -> dieref, NULL); type = alloc_utype (dip -> dieref, NULL);
} }
TYPE_CODE (type) = TYPE_CODE_ENUM; TYPE_CODE (type) = TYPE_CODE_ENUM;
tpart1 = "enum ";
/* Some compilers try to be helpful by inventing "fake" names for anonymous /* Some compilers try to be helpful by inventing "fake" names for anonymous
enums, structures, and unions, like "~0fake". Thanks, but no thanks. */ enums, structures, and unions, like "~0fake" or ".0fake". Thanks, but
if (dip -> at_name == NULL no thanks... */
|| *dip -> at_name == '~' if (dip -> at_name != NULL
|| *dip -> at_name == '.') && *dip -> at_name != '~'
&& *dip -> at_name != '.')
{ {
tpart2 = "{...}"; TYPE_NAME (type) = obconcat ("enum", " ", dip -> at_name);
} else {
tpart2 = dip -> at_name;
} }
if (dip -> at_byte_size == 0) if (dip -> at_byte_size != 0)
{
tpart3 = " <opaque>";
}
else
{ {
TYPE_LENGTH (type) = dip -> at_byte_size; TYPE_LENGTH (type) = dip -> at_byte_size;
tpart3 = "";
} }
TYPE_NAME (type) = concat (tpart1, tpart2, tpart3, NULL);
if ((scan = dip -> at_element_list) != NULL) if ((scan = dip -> at_element_list) != NULL)
{ {
if (dip -> short_element_list) if (dip -> short_element_list)
@ -1414,6 +1399,16 @@ DEFUN(enum_type, (dip), struct dieinfo *dip)
list -> field.name = savestring (scan, strlen (scan)); list -> field.name = savestring (scan, strlen (scan));
scan += strlen (scan) + 1; scan += strlen (scan) + 1;
nfields++; nfields++;
/* Handcraft a new symbol for this enum member. */
sym = (struct symbol *) obstack_alloc (symbol_obstack,
sizeof (struct symbol));
(void) memset (sym, 0, sizeof (struct symbol));
SYMBOL_NAME (sym) = create_name (list -> field.name, symbol_obstack);
SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
SYMBOL_CLASS (sym) = LOC_CONST;
SYMBOL_TYPE (sym) = type;
SYMBOL_VALUE (sym) = list -> field.bitpos;
add_symbol_to_list (sym, &scope -> symbols);
} }
} }
/* Now create the vector of fields, and record how big it is. This is where /* Now create the vector of fields, and record how big it is. This is where
@ -2668,6 +2663,51 @@ DEFUN(add_psymbol_to_list,
/* /*
LOCAL FUNCTION
add_enum_psymbol -- add enumeration members to partial symbol table
DESCRIPTION
Given pointer to a DIE that is known to be for an enumeration,
extract the symbolic names of the enumeration members and add
partial symbols for them.
*/
static void
DEFUN(add_enum_psymbol, (dip), struct dieinfo *dip)
{
char *scan;
char *listend;
long ltemp;
short stemp;
if ((scan = dip -> at_element_list) != NULL)
{
if (dip -> short_element_list)
{
(void) memcpy (&stemp, scan, sizeof (stemp));
listend = scan + stemp + sizeof (stemp);
scan += sizeof (stemp);
}
else
{
(void) memcpy (&ltemp, scan, sizeof (ltemp));
listend = scan + ltemp + sizeof (ltemp);
scan += sizeof (ltemp);
}
while (scan < listend)
{
scan += sizeof (long);
add_psymbol_to_list (&static_psymbols, scan, VAR_NAMESPACE,
LOC_CONST, 0);
scan += strlen (scan) + 1;
}
}
}
/*
LOCAL FUNCTION LOCAL FUNCTION
add_partial_symbol -- add symbol to partial symbol table add_partial_symbol -- add symbol to partial symbol table
@ -2710,10 +2750,17 @@ DEFUN(add_partial_symbol, (dip), struct dieinfo *dip)
break; break;
case TAG_structure_type: case TAG_structure_type:
case TAG_union_type: case TAG_union_type:
case TAG_enumeration_type:
add_psymbol_to_list (&static_psymbols, dip -> at_name, STRUCT_NAMESPACE, add_psymbol_to_list (&static_psymbols, dip -> at_name, STRUCT_NAMESPACE,
LOC_TYPEDEF, 0); LOC_TYPEDEF, 0);
break; break;
case TAG_enumeration_type:
if (dip -> at_name)
{
add_psymbol_to_list (&static_psymbols, dip -> at_name,
STRUCT_NAMESPACE, LOC_TYPEDEF, 0);
}
add_enum_psymbol (dip);
break;
} }
} }
@ -2730,17 +2777,20 @@ DESCRIPTION
for this compilation unit. Since we cannot follow any sibling for this compilation unit. Since we cannot follow any sibling
chains without reading the complete DIE info for every DIE, chains without reading the complete DIE info for every DIE,
it is probably faster to just sequentially check each one to it is probably faster to just sequentially check each one to
see if it is one of the types we are interested in, and if see if it is one of the types we are interested in, and if so,
so, then extracting all the attributes info and generating a then extract all the attributes info and generate a partial
partial symbol table entry. symbol table entry.
NOTES NOTES
Don't attempt to add anonymous structures, unions, or enumerations Don't attempt to add anonymous structures or unions since they have
since they have no name. Also, for variables and subroutines, no name. Anonymous enumerations however are processed, because we
check that this is the place where the actual definition occurs, want to extract their member names (the check for a tag name is
rather than just a reference to an external. done later).
Also, for variables and subroutines, check that this is the place
where the actual definition occurs, rather than just a reference
to an external.
*/ */
static void static void
@ -2759,6 +2809,8 @@ DEFUN(scan_partial_symbols, (thisdie, enddie), char *thisdie AND char *enddie)
else else
{ {
nextdie = thisdie + di.dielength; nextdie = thisdie + di.dielength;
/* To avoid getting complete die information for every die, we
only do it (below) for the cases we are interested in. */
switch (di.dietag) switch (di.dietag)
{ {
case TAG_global_subroutine: case TAG_global_subroutine:
@ -2774,13 +2826,16 @@ DEFUN(scan_partial_symbols, (thisdie, enddie), char *thisdie AND char *enddie)
case TAG_typedef: case TAG_typedef:
case TAG_structure_type: case TAG_structure_type:
case TAG_union_type: case TAG_union_type:
case TAG_enumeration_type:
completedieinfo (&di); completedieinfo (&di);
if (di.at_name) if (di.at_name)
{ {
add_partial_symbol (&di); add_partial_symbol (&di);
} }
break; break;
case TAG_enumeration_type:
completedieinfo (&di);
add_partial_symbol (&di);
break;
} }
} }
thisdie = nextdie; thisdie = nextdie;