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
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 */