mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-28 23:39:35 +08:00
Several changes to fix misc problems with enums, structs, and unions,
including building symbol table entries for enumeration members.
This commit is contained in:
@ -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
|
||||||
|
179
gdb/dwarfread.c
179
gdb/dwarfread.c
@ -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 *)
|
TYPE_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *)
|
||||||
obstack_alloc (symbol_obstack, sizeof (struct cplus_struct_type));
|
obstack_alloc (symbol_obstack, sizeof (struct cplus_struct_type));
|
||||||
(void) memset (TYPE_CPLUS_SPECIFIC (type), 0,
|
(void) memset (TYPE_CPLUS_SPECIFIC (type), 0,
|
||||||
sizeof (struct cplus_struct_type));
|
sizeof (struct cplus_struct_type));
|
||||||
if (dip -> dietag == TAG_structure_type)
|
switch (dip -> dietag)
|
||||||
{
|
{
|
||||||
|
case TAG_structure_type:
|
||||||
TYPE_CODE (type) = TYPE_CODE_STRUCT;
|
TYPE_CODE (type) = TYPE_CODE_STRUCT;
|
||||||
tpart1 = "struct";
|
tpart1 = "struct";
|
||||||
}
|
break;
|
||||||
else
|
case TAG_union_type:
|
||||||
{
|
|
||||||
TYPE_CODE (type) = TYPE_CODE_UNION;
|
TYPE_CODE (type) = TYPE_CODE_UNION;
|
||||||
tpart1 = "union";
|
tpart1 = "union";
|
||||||
}
|
break;
|
||||||
}
|
default:
|
||||||
else
|
/* Should never happen */
|
||||||
{
|
|
||||||
tpart1 = "";
|
|
||||||
SQUAWK (("missing structure or union tag"));
|
|
||||||
TYPE_CODE (type) = TYPE_CODE_UNDEF;
|
TYPE_CODE (type) = TYPE_CODE_UNDEF;
|
||||||
|
tpart1 = "???";
|
||||||
|
SQUAWK (("missing structure or union tag"));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* 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 (<emp, 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;
|
||||||
|
Reference in New Issue
Block a user