WineDbg: better stab parsing

Eric Pouech eric.pouech at wanadoo.fr
Sat Feb 15 14:30:46 CST 2003


this patch implement another bunch of C++ stabs parsing (which mingw 
emits). this should cover most of bug #990
the patch also contains a small speed up in symbol adding (we were 
looking twice for a symbol when adding it from the ELF headers)
this patch mostly depends on the others winedbg patches, so it should be 
applied last
A+
-- 
Eric Pouech
-------------- next part --------------
Name:          wd_stabscpp
ChangeLog:     
	- added parsing of C++ inheritence information
	- added an internal trace for displaying errors in typedef parsing
	- enhanced ELF symbol management (direct call to AddSymbol in ELF header)	
License:       X11
GenDate:       2003/02/15 20:23:49 UTC
ModifiedFiles: programs/winedbg/stabs.c
AddedFiles:    
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/programs/winedbg/stabs.c,v
retrieving revision 1.4
diff -u -u -r1.4 stabs.c
--- programs/winedbg/stabs.c	30 Jan 2003 01:18:06 -0000	1.4
+++ programs/winedbg/stabs.c	15 Feb 2003 11:24:28 -0000
@@ -4,7 +4,7 @@
  * File stabs.c - read stabs information from the wine executable itself.
  *
  * Copyright (C) 1996, Eric Youngdale.
- *		 1999, 2000 Eric Pouech
+ *		 1999-2003 Eric Pouech
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -43,6 +43,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <stdio.h>
 #ifndef PATH_MAX
 #define PATH_MAX MAX_PATH
 #endif
@@ -280,23 +281,46 @@
     return DEBUG_FileSubNr2StabEnum(filenr,subnr);
 }
 
-struct ParseTypedefData {
+/*#define PTS_DEBUG*/
+struct ParseTypedefData
+{
     char*		ptr;
     char		buf[1024];
     int			idx;
+#ifdef PTS_DEBUG
+    struct PTS_Error 
+    {
+        char*               ptr;
+        unsigned            line;
+    } errors[16];
+    int                 err_idx;
+#endif
 };
 
+#ifdef PTS_DEBUG
+static void PTS_Push(struct ParseTypedefData* ptd, unsigned line)
+{
+    assert(ptd->err_idx < sizeof(ptd->errors) / sizeof(ptd->errors[0]));
+    ptd->errors[ptd->err_idx].line = line;
+    ptd->errors[ptd->err_idx].ptr = ptd->ptr;
+    ptd->err_idx++;
+}
+#define PTS_ABORTIF(ptd, t) do { if (t) { PTS_Push((ptd), __LINE__); return -1;} } while (0)
+#else
+#define PTS_ABORTIF(ptd, t) do { if (t) return -1; } while (0)
+#endif
+
 static int DEBUG_PTS_ReadTypedef(struct ParseTypedefData* ptd, const char* typename,
 				 struct datatype** dt);
 
 static int DEBUG_PTS_ReadID(struct ParseTypedefData* ptd)
 {
-    char*	first = ptd->ptr;
+    char*	        first = ptd->ptr;
     unsigned int	len;
 
-    if ((ptd->ptr = strchr(ptd->ptr, ':')) == NULL) return -1;
+    PTS_ABORTIF(ptd, (ptd->ptr = strchr(ptd->ptr, ':')) == NULL);
     len = ptd->ptr - first;
-    if (len >= sizeof(ptd->buf) - ptd->idx) return -1;
+    PTS_ABORTIF(ptd, len >= sizeof(ptd->buf) - ptd->idx);
     memcpy(ptd->buf + ptd->idx, first, len);
     ptd->buf[ptd->idx + len] = '\0';
     ptd->idx += len + 1;
@@ -309,7 +333,7 @@
     char*	last;
 
     *v = strtol(ptd->ptr, &last, 10);
-    if (last == ptd->ptr) return -1;
+    PTS_ABORTIF(ptd, last == ptd->ptr);
     ptd->ptr = last;
     return 0;
 }
@@ -320,13 +344,13 @@
     if (*ptd->ptr == '(') {
 	/* '(' <int> ',' <int> ')' */
 	ptd->ptr++;
-	if (DEBUG_PTS_ReadNum(ptd, filenr) == -1) return -1;
-	if (*ptd->ptr++ != ',') return -1;
-	if (DEBUG_PTS_ReadNum(ptd, subnr) == -1) return -1;
-	if (*ptd->ptr++ != ')') return -1;
+	PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, filenr) == -1);
+	PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+	PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, subnr) == -1);
+	PTS_ABORTIF(ptd, *ptd->ptr++ != ')');
     } else {
     	*filenr = 0;
-	if (DEBUG_PTS_ReadNum(ptd, subnr) == -1) return -1;
+	PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, subnr) == -1);
     }
     return 0;
 }
@@ -335,50 +359,51 @@
 			       int* lo, int* hi)
 {
     /* type ';' <int> ';' <int> ';' */
-    if (DEBUG_PTS_ReadTypedef(ptd, NULL, dt) == -1) return -1;
-    if (*ptd->ptr++ != ';') return -1;	/* ';' */
-    if (DEBUG_PTS_ReadNum(ptd, lo) == -1) return -1;
-    if (*ptd->ptr++ != ';') return -1;	/* ';' */
-    if (DEBUG_PTS_ReadNum(ptd, hi) == -1) return -1;
-    if (*ptd->ptr++ != ';') return -1;	/* ';' */
+    PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, dt) == -1);
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+    PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, lo) == -1);
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
+    PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, hi) == -1);
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');	/* ';' */
     return 0;
 }
 
-static inline int DEBUG_PTS_ReadMethodInfo(struct ParseTypedefData* ptd,
-                                           struct datatype* dt)
+static inline int DEBUG_PTS_ReadMethodInfo(struct ParseTypedefData* ptd)
 {
+    struct datatype* dt;
     char*   tmp;
+    char    mthd;
 
-    if (*ptd->ptr++ == ':')
+    do
     {
-        if (!(tmp = strchr(ptd->ptr, ';'))) return -1;
-        ptd->ptr = tmp + 1;
+        /* get type of return value */
+        PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &dt) == -1);
+        if (*ptd->ptr == ';') ptd->ptr++;
 
-    }
-    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)
+        /* get types of parameters */
+        if (*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++;
+            PTS_ABORTIF(ptd, !(tmp = strchr(ptd->ptr + 1, ';')));
+            ptd->ptr = tmp + 1;
         }
-    }
+        PTS_ABORTIF(ptd, !(*ptd->ptr >= '0' && *ptd->ptr <= '9'));
+        ptd->ptr++;
+        PTS_ABORTIF(ptd, !(ptd->ptr[0] >= 'A' && *ptd->ptr <= 'D'));
+        mthd = *++ptd->ptr;
+        PTS_ABORTIF(ptd, mthd != '.' && mthd != '?' && mthd != '*');
+        ptd->ptr++;
+        if (mthd == '*')
+        {
+            int              ofs;
+            struct datatype* dt;
+
+            PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, &ofs) == -1);
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+            PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &dt) == -1);
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+        }
+    } while (*ptd->ptr != ';');
+    ptd->ptr++;
 
     return 0;
 }
@@ -387,77 +412,132 @@
                                           struct datatype* sdt)
 {
     int			sz, ofs;
-    char*		last;
     struct datatype*	adt;
+    struct datatype*	dt = NULL;
     int			idx;
     int			doadd;
-    BOOL                inMethod;
 
-    sz = strtol(ptd->ptr, &last, 10);
-    if (last == ptd->ptr) return -1;
-    ptd->ptr = last;
+    PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, &sz) == -1);
 
     doadd = DEBUG_SetStructSize(sdt, sz);
+    if (*ptd->ptr == '!') /* C++ inheritence */
+    {
+        int     num_classes;
+        char    tmp[256];
+
+        ptd->ptr++;
+        PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, &num_classes) == -1);
+        PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+        while (--num_classes >= 0)
+        {
+            ptd->ptr += 2; /* skip visibility and inheritence */
+            PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, &ofs) == -1);
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+
+            PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &adt) == -1);
+
+            snprintf(tmp, sizeof(tmp), "__inherited_class_%s", DEBUG_GetName(adt));
+            /* FIXME: DEBUG_GetObjectSize will not always work, especially when adt
+             * has just been seen as a forward definition and not the real stuff yet.
+             * As we don't use much the size of members in structs, this may not
+             * be much of a problem
+             */
+            if (doadd) DEBUG_AddStructElement(sdt, tmp, adt, ofs, DEBUG_GetObjectSize(adt) * 8); 
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+        }
+        
+    }
     /* if the structure has already been filled, just redo the parsing
      * but don't store results into the struct
      * FIXME: there's a quite ugly memory leak in there...
      */
 
     /* Now parse the individual elements of the structure/union. */
-    while (*ptd->ptr != ';') {
+    while (*ptd->ptr != ';') 
+    {
 	/* agg_name : type ',' <int:offset> ',' <int:size> */
 	idx = ptd->idx;
 
-	if (DEBUG_PTS_ReadID(ptd) == -1) return -1;
+        if (ptd->ptr[0] == '$' && ptd->ptr[1] == 'v')
+        {
+            int                 x;
+
+            if (ptd->ptr[2] == 'f')
+            {
+                /* C++ virtual method table */
+                ptd->ptr += 3;
+                DEBUG_ReadTypeEnum(&ptd->ptr);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ':');
+                PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &dt) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+                PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, &x) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+                ptd->idx = idx;
+                continue;
+            }
+            else if (ptd->ptr[2] == 'b')
+            {
+                ptd->ptr += 3;
+                PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &dt) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ':');
+                PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &dt) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+                PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, &x) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+                ptd->idx = idx;
+                continue;
+            }
+        }
+
+	PTS_ABORTIF(ptd, DEBUG_PTS_ReadID(ptd) == -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++; 
-            {
-                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;
+            DEBUG_PTS_ReadMethodInfo(ptd);
+            ptd->idx = idx;
+            continue;
         }
         else
         {
-            inMethod = FALSE;
+            /* skip C++ member protection /0 /1 or /2 */
+            if (*ptd->ptr == '/') ptd->ptr += 2;
         }
-        
-	if (DEBUG_PTS_ReadTypedef(ptd, NULL, &adt) == -1) return -1;
-	if (!adt) return -1;
+	PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &adt) == -1);
 
-	if (*ptd->ptr != ',')
-        {
-            if (!inMethod) return -1;
-            ptd->ptr++;
-        }
-        else
+        switch (*ptd->ptr++)
         {
-            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;
+        case ',':
+            PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, &ofs) == -1);
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+            PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, &sz) == -1);
+            PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
 
             if (doadd) DEBUG_AddStructElement(sdt, ptd->buf + idx, adt, ofs, sz);
+            break;
+        case ':':
+            {
+                char* tmp;
+                /* method parameters... terminated by ';' */
+                PTS_ABORTIF(ptd, !(tmp = strchr(ptd->ptr, ';')));
+                ptd->ptr = tmp + 1;
+            }
+            break;
+        default:
+            PTS_ABORTIF(ptd, TRUE);
         }
 	ptd->idx = idx;
     }
-    ptd->ptr++; /* ';' */
+    PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+    if (*ptd->ptr == '~')
+    {
+        ptd->ptr++;
+        PTS_ABORTIF(ptd, *ptd->ptr++ != '%');
+        PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &dt) == -1);
+        PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
+    }
     return 0;
 }
 
@@ -469,9 +549,9 @@
 
     while (*ptd->ptr != ';') {
 	idx = ptd->idx;
-	if (DEBUG_PTS_ReadID(ptd) == -1) return -1;
-	if (DEBUG_PTS_ReadNum(ptd, &ofs) == -1) return -1;
-	if (*ptd->ptr++ != ',') return -1;
+	PTS_ABORTIF(ptd, DEBUG_PTS_ReadID(ptd) == -1);
+	PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, &ofs) == -1);
+	PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
 	DEBUG_AddStructElement(edt, ptd->buf + idx, NULL, ofs, 0);
 	ptd->idx = idx;
     }
@@ -487,10 +567,10 @@
 
     /* ar<typeinfo_nodef>;<int>;<int>;<typeinfo> */
 
-    if (*ptd->ptr++ != 'r') return -1;
+    PTS_ABORTIF(ptd, *ptd->ptr++ != 'r');
     /* FIXME: range type is lost, always assume int */
-    if (DEBUG_PTS_ReadRange(ptd, &rdt, &lo, &hi) == -1) return -1;
-    if (DEBUG_PTS_ReadTypedef(ptd, NULL, &rdt) == -1) return -1;
+    PTS_ABORTIF(ptd, DEBUG_PTS_ReadRange(ptd, &rdt, &lo, &hi) == -1);
+    PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &rdt) == -1);
 
     DEBUG_SetArrayParams(adt, lo, hi, rdt);
     return 0;
@@ -505,7 +585,6 @@
     struct datatype* 	dt1;		/* intermediate data type (scope is limited) */
     struct datatype* 	dt2;		/* intermediate data type: t1=t2=new_dt */
     int			filenr1, subnr1;
-    int			filenr2 = 0, subnr2 = 0;
 
     /* things are a bit complicated because of the way the typedefs are stored inside
      * the file (we cannot keep the struct datatype** around, because address can
@@ -513,14 +592,12 @@
      * DEBUG_FileSubNr2StabEnum to keep the correct values around
      * (however, keeping struct datatype* is valid))
      */
-    if (DEBUG_PTS_ReadTypeReference(ptd, &filenr1, &subnr1) == -1) return -1;
+    PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypeReference(ptd, &filenr1, &subnr1) == -1);
 
     while (*ptd->ptr == '=') {
 	ptd->ptr++;
-	if (new_dt) {
-	    DEBUG_Printf(DBG_CHN_MESG, "Bad recursion (1) in typedef\n");
-	    return -1;
-	}
+	PTS_ABORTIF(ptd, new_dt != NULL);
+
 	/* first handle attribute if any */
 	switch (*ptd->ptr) {
 	case '@':
@@ -531,7 +608,7 @@
 		    ptd->ptr -= 2;
 		    return -1;
 		}
-		if (*ptd->ptr++ != ';') return -1;
+		PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
 	    }
 	    break;
 	}
@@ -540,56 +617,37 @@
 	case '*':
         case '&':
 	    new_dt = DEBUG_NewDataType(DT_POINTER, NULL);
-	    if (DEBUG_PTS_ReadTypedef(ptd, NULL, &ref_dt) == -1) return -1;
+	    PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &ref_dt) == -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;
+            PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, typename, &new_dt) == -1);
 	    break;
 	case '(':
 	    ptd->ptr--;
-	    /* doit a two level by hand, otherwise we'd need a stack */
-	    if (filenr2 || subnr2) {
-		DEBUG_Printf(DBG_CHN_MESG, "Bad recursion (2) in typedef\n");
-		return -1;
-	    }
-	    if (DEBUG_PTS_ReadTypeReference(ptd, &filenr2, &subnr2) == -1) return -1;
-
-	    dt1 = *DEBUG_FileSubNr2StabEnum(filenr1, subnr1);
-	    dt2 = *DEBUG_FileSubNr2StabEnum(filenr2, subnr2);
-
-	    if (!dt1 && dt2) {
-		new_dt = dt2;
-		filenr2 = subnr2 = 0;
-	    } else if (!dt1 && !dt2)  {
-		new_dt = NULL;
-	    } else {
-		DEBUG_Printf(DBG_CHN_MESG, "Unknown condition %08lx %08lx (%s)\n",
-			     (unsigned long)dt1, (unsigned long)dt2, ptd->ptr);
-		return -1;
-	    }
+            PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, typename, &new_dt) == -1);
 	    break;
 	case 'a':
 	    new_dt = DEBUG_NewDataType(DT_ARRAY, NULL);
-	    if (DEBUG_PTS_ReadArray(ptd, new_dt) == -1) return -1;
+	    PTS_ABORTIF(ptd, DEBUG_PTS_ReadArray(ptd, new_dt) == -1);
 	    break;
 	case 'r':
 	    new_dt = DEBUG_NewDataType(DT_BASIC, typename);
 	    assert(!*DEBUG_FileSubNr2StabEnum(filenr1, subnr1));
 	    *DEBUG_FileSubNr2StabEnum(filenr1, subnr1) = new_dt;
-	    if (DEBUG_PTS_ReadRange(ptd, &ref_dt, &lo, &hi) == -1) return -1;
+	    PTS_ABORTIF(ptd, DEBUG_PTS_ReadRange(ptd, &ref_dt, &lo, &hi) == -1);
 	    /* should perhaps do more here... */
 	    break;
 	case 'f':
 	    new_dt = DEBUG_NewDataType(DT_FUNC, NULL);
-	    if (DEBUG_PTS_ReadTypedef(ptd, NULL, &ref_dt) == -1) return -1;
+	    PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &ref_dt) == -1);
 	    DEBUG_SetPointerType(new_dt, ref_dt);
 	    break;
 	case 'e':
 	    new_dt = DEBUG_NewDataType(DT_ENUM, NULL);
-	    if (DEBUG_PTS_ReadEnum(ptd, new_dt) == -1) return -1;
+	    PTS_ABORTIF(ptd, DEBUG_PTS_ReadEnum(ptd, new_dt) == -1);
 	    break;
 	case 's':
 	case 'u':
@@ -612,7 +670,7 @@
 		/* should check typename is the same too */
 		new_dt = dt1;
 	    }
-	    if (DEBUG_PTS_ReadAggregate(ptd, new_dt) == -1) return -1;
+	    PTS_ABORTIF(ptd, DEBUG_PTS_ReadAggregate(ptd, new_dt) == -1);
 	    break;
 	case 'x':
 	    switch (*ptd->ptr++) {
@@ -622,16 +680,16 @@
 	    }
 
 	    idx = ptd->idx;
-	    if (DEBUG_PTS_ReadID(ptd) == -1) return -1;
+	    PTS_ABORTIF(ptd, DEBUG_PTS_ReadID(ptd) == -1);
 	    new_dt = DEBUG_NewDataType(lo, ptd->buf + idx);
 	    ptd->idx = idx;
 	    break;
 	case '-':
-	    if (DEBUG_PTS_ReadNum(ptd, &lo) == -1) {
-		DEBUG_Printf(DBG_CHN_MESG, "Should be a number (%s)...\n", ptd->ptr);
-		return -1;
-	    } else {
+            {
                 enum debug_type_basic basic = DT_BASIC_LAST;
+
+                PTS_ABORTIF(ptd, DEBUG_PTS_ReadNum(ptd, &lo) == -1);
+
                 switch (lo)
                 {
                 case  1: basic = DT_BASIC_INT; break;
@@ -664,15 +722,10 @@
                 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);
-                    return -1;
-                }
-                if (!(new_dt = DEBUG_GetBasicType(basic))) {
-                    DEBUG_Printf(DBG_CHN_MESG, "Basic type %d not found\n", basic);
-                    return -1;
+                    PTS_ABORTIF(ptd, 1);
                 }
-                if (*ptd->ptr++ != ';') return -1;
+                PTS_ABORTIF(ptd, !(new_dt = DEBUG_GetBasicType(basic)));
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
             }
 	    break;
         case '#':
@@ -680,27 +733,24 @@
             if (*ptd->ptr == '#')
             {
                 ptd->ptr++;
-                if (DEBUG_PTS_ReadTypedef(ptd, NULL, &ref_dt) == -1) return -1;
+                PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &ref_dt) == -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;
+                PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &cls_dt) == -1);
+                PTS_ABORTIF(ptd, *ptd->ptr++ != ',');
+                PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &ref_dt) == -1);
                 DEBUG_SetPointerType(new_dt, ref_dt);
-                while (*ptd->ptr++ == ',')
+                while (*ptd->ptr == ',')
                 {
-                    if (DEBUG_PTS_ReadTypedef(ptd, NULL, &pmt_dt) == -1) return -1;
+                    ptd->ptr++;
+                    PTS_ABORTIF(ptd, DEBUG_PTS_ReadTypedef(ptd, NULL, &pmt_dt) == -1);
                 }
             }
-            if (DEBUG_PTS_ReadMethodInfo(ptd, new_dt) == -1) return -1;
-            
             break;
 	default:
 	    DEBUG_Printf(DBG_CHN_MESG, "Unknown type '%c'\n", ptd->ptr[-1]);
@@ -708,23 +758,14 @@
 	}
     }
 
-    if ((filenr2 || subnr2) && !*DEBUG_FileSubNr2StabEnum(filenr2, subnr2)) {
-	if (!new_dt) {
-	    /* this should be a basic type, define it, or even void */
+    if (!new_dt)
+    {
+        /* is it a forward declaration that has been filled ? */
+	new_dt = *DEBUG_FileSubNr2StabEnum(filenr1, subnr1);
+        /* if not, this should then be a basic type: define it, or even void */
+        if (!new_dt)
 	    new_dt = DEBUG_NewDataType(DT_BASIC, typename);
-	}
-	*DEBUG_FileSubNr2StabEnum(filenr2, subnr2) = new_dt;
-    }
-
-    if (!new_dt) {
-	dt1 = *DEBUG_FileSubNr2StabEnum(filenr1, subnr1);
-	if (!dt1) {
-	    DEBUG_Printf(DBG_CHN_MESG, "Nothing has been defined <%s>\n", ptd->ptr);
-	    return -1;
-	}
-	*ret_dt = dt1;
-	return 0;
-    }
+    }            
 
     *DEBUG_FileSubNr2StabEnum(filenr1, subnr1) = *ret_dt = new_dt;
 
@@ -748,8 +789,17 @@
     /* check for already existing definition */
 
     ptd.idx = 0;
-    if ((ptd.ptr = strchr(ptr, ':'))) {
-	ptd.ptr++;
+#ifdef PTS_DEBUG
+    ptd.err_idx = 0;
+#endif
+    for (ptd.ptr = ptr - 1; ;)
+    {
+        ptd.ptr = strchr(ptd.ptr + 1, ':');
+        if (ptd.ptr == NULL || *++ptd.ptr != ':') break;
+    }
+
+    if (ptd.ptr)
+    {
 	if (*ptd.ptr != '(') ptd.ptr++;
         /* most of type definitions take one char, except Tt */
 	if (*ptd.ptr != '(') ptd.ptr++;
@@ -757,7 +807,23 @@
     }
 
     if (ret == -1 || *ptd.ptr) {
+#ifdef PTS_DEBUG
+        int     i;
+	DEBUG_Printf(DBG_CHN_MESG, "Failure on %s\n", ptr);
+        if (ret == -1)
+        {
+            for (i = 0; i < ptd.err_idx; i++)
+            {
+                DEBUG_Printf(DBG_CHN_MESG, "[%d]: line %d => %s\n", 
+                             i, ptd.errors[i].line, ptd.errors[i].ptr);
+            }
+        }
+        else
+            DEBUG_Printf(DBG_CHN_MESG, "[0]: => %s\n", ptd.ptr);
+            
+#else
 	DEBUG_Printf(DBG_CHN_MESG, "Failure on %s at %s\n", ptr, ptd.ptr);
+#endif
 	return FALSE;
     }
 
@@ -767,34 +833,33 @@
 static struct datatype *
 DEBUG_ParseStabType(const char * stab)
 {
-  char * c;
+    const char* c = stab - 1;
 
-  /*
-   * Look through the stab definition, and figure out what datatype
-   * this represents.  If we have something we know about, assign the
-   * type.
-   * According to "The \"stabs\" debug format" (Rev 2.130) the name may be
-   * a C++ name and contain double colons e.g. foo::bar::baz:t5=*6.  Not
-   * yet implemented.
-   */
-  c = strchr(stab, ':');
-  if( c == NULL )
-      return NULL;
+    /*
+     * Look through the stab definition, and figure out what datatype
+     * this represents.  If we have something we know about, assign the
+     * type.
+     * According to "The \"stabs\" debug format" (Rev 2.130) the name may be
+     * a C++ name and contain double colons e.g. foo::bar::baz:t5=*6.
+     */
+    do
+    {
+        if ((c = strchr(c + 1, ':')) == NULL) return NULL;
+    } while (*++c == ':');
 
-  c++;
-  /*
-   * The next characters say more about the type (i.e. data, function, etc)
-   * of symbol.  Skip them.  (C++ for example may have Tt).
-   * Actually this is a very weak description; I think Tt is the only
-   * multiple combination we should see.
-   */
-  while (*c && *c != '(' && !isdigit(*c))
-    c++;
-  /*
-   * The next is either an integer or a (integer,integer).
-   * The DEBUG_ReadTypeEnum takes care that stab_types is large enough.
-   */
-  return *DEBUG_ReadTypeEnum(&c);
+    /*
+     * The next characters say more about the type (i.e. data, function, etc)
+     * of symbol.  Skip them.  (C++ for example may have Tt).
+     * Actually this is a very weak description; I think Tt is the only
+     * multiple combination we should see.
+     */
+    while (*c && *c != '(' && !isdigit(*c))
+        c++;
+    /*
+     * The next is either an integer or a (integer,integer).
+     * The DEBUG_ReadTypeEnum takes care that stab_types is large enough.
+     */
+    return *DEBUG_ReadTypeEnum((char**)&c);
 }
 
 enum DbgInfoLoad DEBUG_ParseStabs(char * addr, unsigned int load_offset,
@@ -1175,19 +1240,8 @@
 	  continue;
 	}
 
-      /*
-       * See if we already have something for this symbol.
-       * If so, ignore this entry, because it would have come from the
-       * stabs or from a previous symbol.  If the value is different,
-       * we will have to keep the darned thing, because there can be
-       * multiple local symbols by the same name.
-       */
-      if(    (DEBUG_GetSymbolValue(symname, -1, &new_value, FALSE ) == gsv_found)
-	  && (new_value.addr.off == (load_addr + symp->st_value)) )
-	  continue;
-
-      new_value.addr.seg = 0;
       new_value.type = NULL;
+      new_value.addr.seg = 0;
       new_value.addr.off = load_addr + symp->st_value;
       new_value.cookie = DV_TARGET;
       flags = SYM_WINE | ((ELF32_ST_TYPE(symp->st_info) == STT_FUNC)


More information about the wine-patches mailing list