C++ and winedbg: testers wanted

Eric Pouech eric.pouech at wanadoo.fr
Sat Jan 11 11:22:51 CST 2003


as some folks have already noticed, loading ELF modules with C++ 
compilation units gave a zillion of traces while parsing debug info in 
winedbg
this patch should silence this type of output

it won't however add the C++ ABI to the debugger: heavy C++ debugging 
will require gdb (and also DwarfII debug info; stabs is so broken in 
this respect)

on the C++ front, what should be possible is:
- every class should be seen as a regular structures
- non virtual methods will be available as functions (of course, this 
will be seen as a regular parameter, and functions will be seen as 
undecorated names... this may recall to some of us the old good days of 
cfront ;-)

anyway, as gcc has some discrepencies it its stabs output in its 
version, I'd like to get some feedback of people loading C++ info into 
winedbg
I already tested gcc 3.2 and 2.96, but results from 2.95, 3.0 and 3.3 
would be appreciated

TIA
A+
-- 
Eric Pouech
-------------- next part --------------
Name:          wd_stabs
ChangeLog:     
	- added experimental parsing for C++ code (but winedbg doesn't support C++ ABI)
	- now loading symbols for included files
License:       X11
GenDate:       2003/01/11 17:14:34 UTC
ModifiedFiles: programs/winedbg/stabs.c
AddedFiles:    
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/stabs.c,v
retrieving revision 1.3
diff -u -u -r1.3 stabs.c
--- programs/winedbg/stabs.c	29 Sep 2002 18:35:31 -0000	1.3
+++ programs/winedbg/stabs.c	11 Jan 2003 17:14:30 -0000
@@ -31,6 +31,8 @@
  *     available (hopefully) from http:\\sources.redhat.com\gdb\onlinedocs
  */
 
+#define WITH_CPP_STABS_PARSING 1
+
 #include "config.h"
 
 #include <sys/types.h>
@@ -269,13 +271,13 @@
 
     if (**x=='(') {
 	(*x)++;					/* '(' */
-	filenr=strtol(*x,x,10);			/* <int> */
+	filenr=strtol(*x,x,10);	                /* <int> */
 	(*x)++;					/* ',' */
-	subnr=strtol(*x,x,10);			/* <int> */
+	subnr=strtol(*x,x,10);		        /* <int> */
 	(*x)++;					/* ')' */
     } else {
     	filenr = 0;
-	subnr = strtol(*x,x,10);		/* <int> */
+	subnr = strtol(*x,x,10);        	/* <int> */
     }
     return DEBUG_FileSubNr2StabEnum(filenr,subnr);
 }
@@ -343,14 +345,58 @@
     if (*ptd->ptr++ != ';') return -1;	/* ';' */
     return 0;
 }
+#ifdef WITH_CPP_STABS_PARSING
+static inline int DEBUG_PTS_ReadMethodInfo(struct ParseTypedefData* ptd, 
+                                           struct datatype* dt)
+{
+    char*   tmp;
+
+    if (*ptd->ptr++ == ':')
+    {
+        if (!(tmp = strchr(ptd->ptr, ';'))) return -1;
+        ptd->ptr = tmp + 1;
+
+    }
+    if (!(*ptd->ptr >= '0' && *ptd->ptr <= '9')) return -1;
+    ptd->ptr++;
+    if (!(ptd->ptr[0] >= 'A' && *ptd->ptr <= 'D')) return -1;
+    ptd->ptr++;
+    if (*ptd->ptr++ != '.') return -1;
+    if (*ptd->ptr != ';')
+    {
+        while (*ptd->ptr)
+        {
+            /* some GCC versions (2.96 for example) really spit out wrongly defined 
+             * stabs... in some cases, the methods are not correctly handled
+             * so just swallow the garbage until either .; (end of method) 
+             * or ;; (end of struct) are found
+             */
+            if (ptd->ptr[0] == '.' && ptd->ptr[1] == ';')
+            {
+                ptd->ptr++;
+                break;
+            }
+            if (ptd->ptr[0] == ';' && ptd->ptr[1] == ';')
+                break;
+            ptd->ptr++;
+        }
+    }
+
+    return 0;
+}
+#endif
 
-static inline int DEBUG_PTS_ReadAggregate(struct ParseTypedefData* ptd, struct datatype* sdt)
+static inline int DEBUG_PTS_ReadAggregate(struct ParseTypedefData* ptd, 
+                                          struct datatype* sdt)
 {
     int			sz, ofs;
     char*		last;
     struct datatype*	adt;
     int			idx;
     int			doadd;
+#ifdef WITH_CPP_STABS_PARSING
+    BOOL                inMethod;
+#endif
 
     sz = strtol(ptd->ptr, &last, 10);
     if (last == ptd->ptr) return -1;
@@ -366,29 +412,67 @@
     while (*ptd->ptr != ';') {
 	/* agg_name : type ',' <int:offset> ',' <int:size> */
 	idx = ptd->idx;
+
 	if (DEBUG_PTS_ReadID(ptd) == -1) return -1;
         /* Ref. TSDF R2.130 Section 7.4.  When the field name is a method name
          * it is followed by two colons rather than one.
          */
-        if (*ptd->ptr == ':') ptd->ptr++;
+        if (*ptd->ptr == ':')
+        {
+            ptd->ptr++; 
+#ifdef WITH_CPP_STABS_PARSING
+            {
+                char* psemic = strchr(ptd->ptr, ';');
+                char* psharp = strchr(ptd->ptr, '#');
 
+                if (!psharp || psharp > psemic)
+                {
+                    struct datatype*	dt = NULL;
+                    /* FIXME: hack... this shall be a ctor */
+                    if (DEBUG_PTS_ReadTypedef(ptd, NULL, &dt) == -1) return -1;
+                    if (DEBUG_PTS_ReadMethodInfo(ptd, dt) == -1) return -1;
+                    if (*ptd->ptr++ != ';') return -1;
+                    ptd->idx = idx;
+                    continue;
+                }
+            }
+            inMethod = TRUE;
+        }
+        else
+        {
+            inMethod = FALSE;
+#endif
+        }
+        
 	if (DEBUG_PTS_ReadTypedef(ptd, NULL, &adt) == -1) return -1;
 	if (!adt) return -1;
 
-	if (*ptd->ptr++ != ',') return -1;
-	if (DEBUG_PTS_ReadNum(ptd, &ofs) == -1) return -1;
-	if (*ptd->ptr++ != ',') return -1;
-	if (DEBUG_PTS_ReadNum(ptd, &sz) == -1) return -1;
-	if (*ptd->ptr++ != ';') return -1;
+	if (*ptd->ptr != ',')
+        {
+#ifdef WITH_CPP_STABS_PARSING
+            if (!inMethod) 
+#endif
+                return -1;
+            ptd->ptr++;
+        }
+        else
+        {
+            ptd->ptr++;
+            if (DEBUG_PTS_ReadNum(ptd, &ofs) == -1) return -1;
+            if (*ptd->ptr++ != ',') return -1;
+            if (DEBUG_PTS_ReadNum(ptd, &sz) == -1) return -1;
+            if (*ptd->ptr++ != ';') return -1;
 
-	if (doadd) DEBUG_AddStructElement(sdt, ptd->buf + idx, adt, ofs, sz);
+            if (doadd) DEBUG_AddStructElement(sdt, ptd->buf + idx, adt, ofs, sz);
+        }
 	ptd->idx = idx;
     }
     ptd->ptr++; /* ';' */
     return 0;
 }
 
-static inline int DEBUG_PTS_ReadEnum(struct ParseTypedefData* ptd, struct datatype* edt)
+static inline int DEBUG_PTS_ReadEnum(struct ParseTypedefData* ptd, 
+                                     struct datatype* edt)
 {
     int			ofs;
     int			idx;
@@ -405,7 +489,8 @@
     return 0;
 }
 
-static inline int DEBUG_PTS_ReadArray(struct ParseTypedefData* ptd, struct datatype* adt)
+static inline int DEBUG_PTS_ReadArray(struct ParseTypedefData* ptd, 
+                                      struct datatype* adt)
 {
     int			lo, hi;
     struct datatype*	rdt;
@@ -463,14 +548,17 @@
 	/* then the real definitions */
 	switch (*ptd->ptr++) {
 	case '*':
+#ifdef WITH_CPP_STABS_PARSING
+        case '&':
+#endif
 	    new_dt = DEBUG_NewDataType(DT_POINTER, NULL);
 	    if (DEBUG_PTS_ReadTypedef(ptd, NULL, &ref_dt) == -1) return -1;
 	    DEBUG_SetPointerType(new_dt, ref_dt);
            break;
-       case 'k': /* 'const' modifier */
-       case 'B': /* 'volatile' modifier */
-           /* just kinda ignore the modifier, I guess -gmt */
-           if (DEBUG_PTS_ReadTypedef(ptd, NULL, &new_dt) == -1) return -1;
+        case 'k': /* 'const' modifier */
+        case 'B': /* 'volatile' modifier */
+            /* just kinda ignore the modifier, I guess -gmt */
+            if (DEBUG_PTS_ReadTypedef(ptd, NULL, &new_dt) == -1) return -1;
 	    break;
 	case '(':
 	    ptd->ptr--;
@@ -588,7 +676,8 @@
                 case 31: basic = DT_BASIC_LONGLONGINT; break;
                 case 32: basic = DT_BASIC_ULONGLONGINT; break;
                 default:
-                    DEBUG_Printf(DBG_CHN_MESG, "Unsupported integral type (%d/%d)\n", lo, sz);
+                    DEBUG_Printf(DBG_CHN_MESG, 
+                                 "Unsupported integral type (%d/%d)\n", lo, sz);
                     return -1;
                 }
                 if (!(new_dt = DEBUG_GetBasicType(basic))) {
@@ -598,6 +687,35 @@
                 if (*ptd->ptr++ != ';') return -1;
             }
 	    break;
+#ifdef WITH_CPP_STABS_PARSING
+        case '#':
+	    new_dt = DEBUG_NewDataType(DT_FUNC, NULL);
+            if (*ptd->ptr == '#')
+            {
+                ptd->ptr++;
+                if (DEBUG_PTS_ReadTypedef(ptd, NULL, &ref_dt) == -1) return -1;
+                DEBUG_SetPointerType(new_dt, ref_dt);
+                if (*ptd->ptr++ != ';') return -1;
+                
+            }
+            else
+            {
+                struct datatype* cls_dt;
+                struct datatype* pmt_dt;
+
+                if (DEBUG_PTS_ReadTypedef(ptd, NULL, &cls_dt) == -1) return -1;
+                if (*ptd->ptr++ != ',') return -1;
+                if (DEBUG_PTS_ReadTypedef(ptd, NULL, &ref_dt) == -1) return -1;
+                DEBUG_SetPointerType(new_dt, ref_dt);
+                while (*ptd->ptr++ == ',')
+                {
+                    if (DEBUG_PTS_ReadTypedef(ptd, NULL, &pmt_dt) == -1) return -1;
+                }
+            }
+            if (DEBUG_PTS_ReadMethodInfo(ptd, new_dt) == -1) return -1;
+            
+            break;
+#endif
 	default:
 	    DEBUG_Printf(DBG_CHN_MESG, "Unknown type '%c'\n", ptd->ptr[-1]);
 	    return -1;
@@ -647,11 +765,15 @@
     if ((ptd.ptr = strchr(ptr, ':'))) {
 	ptd.ptr++;
 	if (*ptd.ptr != '(') ptd.ptr++;
+#ifdef WITH_CPP_STABS_PARSING
+        /* most of type definitions take one char, except Tt */
+	if (*ptd.ptr != '(') ptd.ptr++;
+#endif
 	ret = DEBUG_PTS_ReadTypedef(&ptd, typename, &dt);
     }
 
     if (ret == -1 || *ptd.ptr) {
-	DEBUG_Printf(DBG_CHN_MESG, "failure on %s at %s\n", ptr, ptd.ptr);
+	DEBUG_Printf(DBG_CHN_MESG, "Failure on %s at %s\n", ptr, ptd.ptr);
 	return FALSE;
     }
 
@@ -729,7 +851,7 @@
 
   strtabinc = 0;
   stabbuff[0] = '\0';
-  for(i=0; i < nstab; i++, stab_ptr++ )
+  for (i = 0; i < nstab; i++, stab_ptr++)
     {
       ptr = strs + (unsigned int) stab_ptr->n_un.n_name;
       if( ptr[strlen(ptr) - 1] == '\\' )
@@ -944,7 +1066,7 @@
             }
 #endif
 
-          if( *ptr == '\0' )
+          if( *ptr == '\0' ) /* end of N_SO file */
             {
               /*
                * Nuke old path.
@@ -1004,7 +1127,7 @@
       stabbuff[0] = '\0';
 
 #if 0
-      DEBUG_Printf(DBG_CHN_MESG, "%d %x %s\n", stab_ptr->n_type,
+      DEBUG_Printf(DBG_CHN_MESG, "0x%02x %x %s\n", stab_ptr->n_type,
 		   (unsigned int) stab_ptr->n_value,
 		   strs + (unsigned int) stab_ptr->n_un.n_name);
 #endif
@@ -1044,7 +1167,7 @@
   nsym = symtab->sh_size / sizeof(*symp);
   strp = (char *) (addr + strtab->sh_offset);
 
-  for(i=0; i < nsym; i++, symp++)
+  for (i = 0; i < nsym; i++, symp++)
     {
       /*
        * Ignore certain types of entries which really aren't of that much
@@ -1165,7 +1288,7 @@
     }
 
     if (stabsect == -1 || stabstrsect == -1) {
-	DEBUG_Printf(DBG_CHN_WARN, "no .stab section\n");
+	DEBUG_Printf(DBG_CHN_WARN, "No .stab section\n");
 	goto leave;
     }
 
@@ -1181,7 +1304,7 @@
 	dil = DIL_LOADED;
     } else {
 	dil = DIL_ERROR;
-	DEBUG_Printf(DBG_CHN_WARN, "bad stabs\n");
+	DEBUG_Printf(DBG_CHN_WARN, "Couldn't read correctly read stabs\n");
 	goto leave;
     }
 
@@ -1350,7 +1473,9 @@
    if (filename == NULL) return DIL_ERROR;
    if (DEBUG_FindModuleByName(filename, DMT_ELF)) return DIL_LOADED;
 
+#ifndef WITH_CPP_STABS_PARSING
    if (strstr (filename, "libstdc++")) return DIL_ERROR; /* We know we can't do it */
+#endif
    dil = DEBUG_ProcessElfFile(filename, load_offset, dyn_addr);
 
    /* if relative pathname, try some absolute base dirs */
@@ -1383,6 +1508,7 @@
     for (lm_addr = (u_long)dbg_hdr->r_map; lm_addr; lm_addr = (u_long)lm.l_next) {
 	if (!DEBUG_READ_MEM_VERBOSE((void*)lm_addr, &lm, sizeof(lm)))
 	    return FALSE;
+
 	if (lm.l_addr != 0 &&
 	    DEBUG_READ_MEM_VERBOSE((void*)lm.l_addr, &ehdr, sizeof(ehdr)) &&
 	    ehdr.e_type == ET_DYN && /* only look at dynamic modules */


More information about the wine-devel mailing list