🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

1 total messages Started by David Detlefs Mon, 14 Aug 1989 19:51
G++, anonymous unions and gdb
#348
Author: David Detlefs
Date: Mon, 14 Aug 1989 19:51
173 lines
4755 bytes
Michael et. al. --

Problem: G++ does not produce appropriate symbol table information for
anonymous unions.  Consider the following program:

--------------------------------------------------
struct foo {
  union {
    int i;
    char* j;
  };
};


void main() {
  foo f;
  f.i = 7;
  f.j = "foofoo";
}
--------------------------------------------------

G++ compiles this without complaint, and, as far as I can tell,
correctly.  However, if you compile it with -g, and run it under
gdb, you can get the following script:

b main
Breakpoint 1 at 0xb5: file bug2.c, line 10.
gdb% run
Starting program: /usr0/dld/testing/bug2 

Bpt 1, main (1, 2147481872, 2147481880) (bug2.c line 10)
10	  f.i = 7;
gdb% p f
$1 = {}
gdb% p f.i
there is no field named i
gdb%

The problem is that when G++ generates symbol-table information for
"struct foo" in dbxout.c, it decides that "foo" has no members,
because it has no named members at the top-level.

Below is a fix to dbxout.c that makes G++ produce symbol-table
information that makes gdb treat members of anonymous unions as if
they are top-level members of the classes in which they occur.  That
is, in the above case, you get

gdb% p f
$2 = {i = 0, j = 0x0}
gdb% p f.i
$3 = 0
gdb% 

Ideally, we would also like gdb to print out extra sets of curly
braces to indicate which members of f are parts of the same anonymous
union:

gdb% p f
$2 = {{i = 0, j = 0x0}}
gdb% p f.i
$3 = 0
gdb% 

...But I can't figure out a way to do this.  I suspect that it would
require gdb modifications, since gdb seems to expect each field of a
record to have a name.

In the fix below, note that is important that the solution be
recursive, so that cases such as

--------------------------------------------------
struct bar {
  union {
    int i;
    union {
      float f;
      char* s;
    };
  };
};
--------------------------------------------------

get treated correctly -- bar is considered to have three top-level
members i, f, and s that all start at the same offset.

Here is the fix to dbxout.c:

***After line 172, add:

static void dbxout_field ();

***Change the else clause that begins at line 439 to

	else
	  dbxout_field(tem, type);

***Add the following function:

/* Output a field of a record type to the asm file. */

static void dbxout_field (field, type)
     register tree field, type;
{
  if ( DECL_NAME (field) == 0 )
    if ( TREE_CODE( TREE_TYPE (field) ) == UNION_TYPE ) {
      /* An anonymous union.  Print out a field descriptor for each */
      /* member of the union. */
      tree tem2;
      for (tem2 = TYPE_FIELDS( TREE_TYPE (field) ); tem2;
	   tem2 = TREE_CHAIN (tem2)) {
	dbxout_field(tem2, type);
      }
      return;
    } else
      /* Is a null field, only there to take up space. */
      return;

  /* Otherwise, just output the description of the field. */
  if (use_gdb_dbx_extensions || TREE_CODE (field) != CONST_DECL) {
    /* Continue the line if necessary, but not before the first field.  */
    if (field != TYPE_FIELDS (type))
      CONTIN;
    fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (field)));
    CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (field)));

    if (use_gdb_dbx_extensions)
      {
	putc ('/', asmfile);
#ifdef TREE_PRIVATE
	putc ((TREE_PRIVATE (field) ? '0' :
	       TREE_PROTECTED (field) ? '1' : '2'),
	      asmfile);
#endif
	CHARS (2);
      }

    dbxout_type (TREE_TYPE (field), 0);
    if (TREE_CODE (field) == VAR_DECL)
      {
	if (use_gdb_dbx_extensions)
	  {
	    char *name = XSTR (XEXP (DECL_RTL (field), 0), 0);
	    if (name[0] == '*')
	      name += 1;
	    /* Adding 1 here only works on systems
	       which flush an initial underscore.  */
	    fprintf (asmfile, ":%s;", name+1);
	    CHARS (strlen (name));
	  }
	else
	  {
	    fprintf (asmfile, ",0,0;");
	  }
      }
    else if (TREE_CODE (field) == CONST_DECL)
      {
	/* Only get here if using GDB's extensions to DBX format.  */
	fprintf (asmfile, "~i%d;", TREE_INT_CST_LOW (DECL_INITIAL (field)));
      }
    else
      {
	fprintf (asmfile, ",%d,%d;", DECL_OFFSET (field),
		 TREE_INT_CST_LOW (DECL_SIZE (field)) *
		 DECL_SIZE_UNIT (field));
      }
    CHARS (23);
  }
}


Happier hacking.

Dave
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads