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
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)