C++ and winedbg: testers wanted
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 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 */
participants (1)
-
Eric Pouech