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