WineDbg, C++ and stabs

Eric Pouech eric.pouech at wanadoo.fr
Tue Jan 28 14:16:42 CST 2003


since noone actually sent comment on the stabs/C++ parser for WineDbg, I 
assume that it won't cause any problem at all because of the great 
review it got
in the unlikely (?!) case were no one actually tested it, committing to 
CVS would provide sufficient testing.
So time for merge has come!!!

as already said, this patch won't implement full C++ ABI support in 
WineDbg. It will just let winedbg read C++ information (as it was plain 
C, like in the good old days of cfront), and silence lots of warning 
while loading modules with C++ stabs in them.

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/28 20:12:12 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.
@@ -970,7 +1092,8 @@
            * If this is the main source, enable the debug stuff, otherwise
            * ignore it.
            */
-          in_external_file = !(subpath == NULL || strcmp(ptr, subpath) == 0);
+            in_external_file = !(subpath == NULL || strcmp(ptr, subpath) == 0);
+            in_external_file = FALSE; /* FIXME EPP hack FIXME */;
           break;
         case N_UNDF:
           strs += strtabinc;
@@ -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-patches mailing list