[PATCH 10/10] [WineDump]

Eric Pouech eric.pouech at wanadoo.fr
Wed Nov 29 14:41:05 CST 2006


- added stuff for dumping types from PDB, CV... files

A+
---

 tools/winedump/Makefile.in |    1 
 tools/winedump/msc.c       | 1167 ++++++++++++++++++++++++++++++++++++++++++++
 tools/winedump/pdb.c       |   67 ++-
 tools/winedump/winedump.h  |    2 
 4 files changed, 1218 insertions(+), 19 deletions(-)

diff --git a/tools/winedump/Makefile.in b/tools/winedump/Makefile.in
index 749f4cb..32a2a1d 100644
--- a/tools/winedump/Makefile.in
+++ b/tools/winedump/Makefile.in
@@ -18,6 +18,7 @@ C_SRCS = \
 	main.c \
 	minidump.c \
 	misc.c \
+	msc.c \
 	msmangle.c \
 	ne.c \
 	output.c \
diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c
new file mode 100644
index 0000000..6c9ba58
--- /dev/null
+++ b/tools/winedump/msc.c
@@ -0,0 +1,1167 @@
+/*
+ *	MS debug info dumping utility
+ *
+ * 	Copyright 2006 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <time.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <fcntl.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "winedump.h"
+#include "wine/mscvpdb.h"
+
+#define PSTRING(adr, ofs) \
+    ((const struct p_string*)((const char*)(adr) + (ofs)))
+
+static const char* p_string(const struct p_string* s)
+{
+    static char tmp[256 + 1];
+    memcpy(tmp, s->name, s->namelen);
+    tmp[s->namelen] = '\0';
+    return tmp;
+}
+
+static int numeric_leaf(int* value, const unsigned short int* leaf)
+{
+    unsigned short int type = *leaf++;
+    int length = 2;
+
+    if (type < LF_NUMERIC)
+    {
+        *value = type;
+    }
+    else
+    {
+        switch (type)
+        {
+        case LF_CHAR:
+            length += 1;
+            *value = *(const char*)leaf;
+            break;
+
+        case LF_SHORT:
+            length += 2;
+            *value = *(const short*)leaf;
+            break;
+
+        case LF_USHORT:
+            length += 2;
+            *value = *(const unsigned short*)leaf;
+            break;
+
+        case LF_LONG:
+            length += 4;
+            *value = *(const int*)leaf;
+            break;
+
+        case LF_ULONG:
+            length += 4;
+            *value = *(const unsigned int*)leaf;
+            break;
+
+        case LF_QUADWORD:
+        case LF_UQUADWORD:
+            length += 8;
+            printf(">>> unsupported leaf value\n");
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_REAL32:
+            length += 4;
+            printf(">>> unsupported leaf value\n");
+            *value = 0;    /* FIXME */
+            break;
+
+        case LF_REAL48:
+            length += 6;
+            *value = 0;    /* FIXME */
+            printf(">>> unsupported leaf value\n");
+            break;
+
+        case LF_REAL64:
+            length += 8;
+            *value = 0;    /* FIXME */
+            printf(">>> unsupported leaf value\n");
+            break;
+
+        case LF_REAL80:
+            length += 10;
+            *value = 0;    /* FIXME */
+            printf(">>> unsupported leaf value\n");
+            break;
+
+        case LF_REAL128:
+            length += 16;
+            *value = 0;    /* FIXME */
+            printf(">>> unsupported leaf value\n");
+            break;
+
+        case LF_COMPLEX32:
+            length += 4;
+            *value = 0;    /* FIXME */
+            printf(">>> unsupported leaf value\n");
+            break;
+
+        case LF_COMPLEX64:
+            length += 8;
+            *value = 0;    /* FIXME */
+            printf(">>> unsupported leaf value\n");
+            break;
+
+        case LF_COMPLEX80:
+            length += 10;
+            *value = 0;    /* FIXME */
+            printf(">>> unsupported leaf value\n");
+            break;
+
+        case LF_COMPLEX128:
+            length += 16;
+            *value = 0;    /* FIXME */
+            printf(">>> unsupported leaf value\n");
+            break;
+
+        case LF_VARSTRING:
+            length += 2 + *leaf;
+            *value = 0;    /* FIXME */
+            printf(">>> unsupported leaf value\n");
+            break;
+
+        default:
+	    printf(">>> Unsupported numeric leaf-id %04x\n", type);
+            *value = 0;
+            break;
+        }
+    }
+    return length;
+}
+
+static const char* get_attr(unsigned attr)
+{
+    static char tmp[256];
+
+    switch (attr & 3)
+    {
+    case 0: strcpy(tmp, ""); break;
+    case 1: strcpy(tmp, "private "); break;
+    case 2: strcpy(tmp, "protected "); break;
+    case 3: strcpy(tmp, "public "); break;
+    }
+    switch ((attr >> 2) & 7)
+    {
+    case 0: strcat(tmp, ""); break;
+    case 1: strcat(tmp, "virtual "); break;
+    case 2: strcat(tmp, "static "); break;
+    case 3: strcat(tmp, "friend "); break;
+    case 4: strcat(tmp, "introducing virtual "); break;
+    case 5: strcat(tmp, "pure virtual "); break;
+    case 6: strcat(tmp, "pure introducing virtual "); break;
+    case 7: strcat(tmp, "reserved "); break;
+    }
+    if ((attr >> 5) & 1) strcat(tmp, "pseudo ");
+    if ((attr >> 6) & 1) strcat(tmp, "no-inherit ");
+    if ((attr >> 7) & 1) strcat(tmp, "no-construct ");
+    return tmp;
+}
+
+static void do_field(const unsigned char* start, const unsigned char* end)
+{
+    /*
+     * A 'field list' is a CodeView-specific data type which doesn't
+     * directly correspond to any high-level data type.  It is used
+     * to hold the collection of members of a struct, class, union
+     * or enum type.  The actual definition of that type will follow
+     * later, and refer to the field list definition record.
+     *
+     * As we don't have a field list type ourselves, we look ahead
+     * in the field list to try to find out whether this field list
+     * will be used for an enum or struct type, and create a dummy
+     * type of the corresponding sort.  Later on, the definition of
+     * the 'real' type will copy the member / enumeration data.
+     */
+    const unsigned char*        ptr = start;
+    const char*                 cstr;
+    const struct p_string*      pstr;
+    int leaf_len, value;
+
+    while (ptr < end)
+    {
+        const union codeview_fieldtype* fieldtype = (const union codeview_fieldtype*)ptr;
+
+        if (*ptr >= 0xf0)       /* LF_PAD... */
+        {
+            ptr +=* ptr & 0x0f;
+            continue;
+        }
+
+        switch (fieldtype->generic.id)
+        {
+        case LF_ENUMERATE_V1:
+            leaf_len = numeric_leaf(&value, &fieldtype->enumerate_v1.value);
+            pstr = PSTRING(&fieldtype->enumerate_v1.value, leaf_len);
+            printf("\t\tEnumerate V1: '%s' value:%d\n",
+                   p_string(pstr), value);
+            ptr += 2 + 2 + leaf_len + 1 + pstr->namelen;
+            break;
+
+        case LF_ENUMERATE_V3:
+            leaf_len = numeric_leaf(&value, &fieldtype->enumerate_v3.value);
+            cstr = (const char*)&fieldtype->enumerate_v3.value + leaf_len;
+            printf("\t\tEnumerate V3: '%s' value:%d\n",
+                   cstr, value);
+            ptr += 2 + 2 + leaf_len + strlen(cstr) + 1;
+            break;
+
+        case LF_MEMBER_V1:
+            leaf_len = numeric_leaf(&value, &fieldtype->member_v1.offset);
+            pstr = PSTRING(&fieldtype->member_v1.offset, leaf_len);
+            printf("\t\tMember V1: '%s' type:%x attr:%s @%d\n",
+                   p_string(pstr), fieldtype->member_v1.type,
+                   get_attr(fieldtype->member_v1.attribute), value);
+            ptr += 2 + 2 + 2 + leaf_len + 1 + pstr->namelen;
+            break;
+
+        case LF_MEMBER_V2:
+            leaf_len = numeric_leaf(&value, &fieldtype->member_v2.offset);
+            pstr = PSTRING(&fieldtype->member_v2.offset, leaf_len);
+            printf("\t\tMember V2: '%s' type:%x attr:%s @%d\n",
+                   p_string(pstr), fieldtype->member_v2.type,
+                   get_attr(fieldtype->member_v2.attribute), value);
+            ptr += 2 + 2 + 4 + leaf_len + 1 + pstr->namelen;
+            break;
+
+        case LF_MEMBER_V3:
+            leaf_len = numeric_leaf(&value, &fieldtype->member_v3.offset);
+            cstr = (const char*)&fieldtype->member_v3.offset + leaf_len;
+            printf("\t\tMember V3: '%s' type:%x attr:%s @%d\n",
+                   cstr, fieldtype->member_v3.type, 
+                   get_attr(fieldtype->member_v3.attribute), value);
+            ptr += 2 + 2 + 4 + leaf_len + strlen(cstr) + 1;
+            break;
+
+        case LF_ONEMETHOD_V1:
+            switch ((fieldtype->onemethod_v1.attribute >> 2) & 7)
+            {
+            case 4: case 6:
+                printf("\t\tVirtual-method V1: '%s' attr:%s type:%x vtable_offset:%u\n",
+                       p_string(&fieldtype->onemethod_virt_v1.p_name),
+                       get_attr(fieldtype->onemethod_virt_v1.attribute),
+                       fieldtype->onemethod_virt_v1.type,
+                       fieldtype->onemethod_virt_v1.vtab_offset);
+                ptr += 2 + 2 + 2 + 4 + (1 + fieldtype->onemethod_virt_v1.p_name.namelen);
+                break;
+
+            default:
+                printf("\t\tMethod V1: '%s' attr:%s type:%x\n",
+                       p_string(&fieldtype->onemethod_v1.p_name),
+                       get_attr(fieldtype->onemethod_v1.attribute),
+                       fieldtype->onemethod_v1.type);
+                ptr += 2 + 2 + 2 + (1 + fieldtype->onemethod_v1.p_name.namelen);
+                break;
+            }
+            break;
+
+        case LF_ONEMETHOD_V2:
+            switch ((fieldtype->onemethod_v2.attribute >> 2) & 7)
+            {
+            case 4: case 6:
+                printf("\t\tVirtual-method V2: '%s' attr:%s type:%x vtable_offset:%u\n",
+                       p_string(&fieldtype->onemethod_virt_v2.p_name),
+                       get_attr(fieldtype->onemethod_virt_v2.attribute),
+                       fieldtype->onemethod_virt_v2.type,
+                       fieldtype->onemethod_virt_v2.vtab_offset);
+                ptr += 2 + 2 + 4 + 4 + (1 + fieldtype->onemethod_virt_v2.p_name.namelen);
+                break;
+
+            default:
+                printf("\t\tMethod V2: '%s' attr:%s type:%x\n",
+                       p_string(&fieldtype->onemethod_v2.p_name),
+                       get_attr(fieldtype->onemethod_v2.attribute),
+                       fieldtype->onemethod_v2.type);
+                ptr += 2 + 2 + 4 + (1 + fieldtype->onemethod_v2.p_name.namelen);
+                break;
+            }
+            break;
+
+        case LF_ONEMETHOD_V3:
+            switch ((fieldtype->onemethod_v3.attribute >> 2) & 7)
+            {
+            case 4: case 6:
+                printf("\t\tVirtual-method V3: '%s' attr:%s type:%x vtable_offset:%u\n",
+                       fieldtype->onemethod_virt_v3.name,
+                       get_attr(fieldtype->onemethod_virt_v3.attribute),
+                       fieldtype->onemethod_virt_v3.type,
+                       fieldtype->onemethod_virt_v3.vtab_offset);
+                ptr += 2 + 2 + 4 + 4 + (strlen(fieldtype->onemethod_virt_v3.name) + 1);
+                break;
+
+            default:
+                printf("\t\tMethod V3: '%s' attr:%s type:%x\n",
+                       fieldtype->onemethod_v3.name,
+                       get_attr(fieldtype->onemethod_v3.attribute),
+                       fieldtype->onemethod_v3.type);
+                ptr += 2 + 2 + 4 + (strlen(fieldtype->onemethod_v3.name) + 1);
+                break;
+            }
+            break;
+
+        case LF_METHOD_V1:
+            printf("\t\tMethod V1: '%s' overloaded=#%d method-list=%x\n",
+                   p_string(&fieldtype->method_v1.p_name),
+                   fieldtype->method_v1.count, fieldtype->method_v1.mlist);
+            ptr += 2 + 2 + 2 + (1 + fieldtype->method_v1.p_name.namelen);
+            break;
+
+        case LF_METHOD_V2:
+            printf("\t\tMethod V2: '%s' overloaded=#%d method-list=%x\n",
+                   p_string(&fieldtype->method_v2.p_name),
+                   fieldtype->method_v2.count, fieldtype->method_v2.mlist);
+            ptr += 2 + 2 + 4 + (1 + fieldtype->method_v2.p_name.namelen);
+            break;
+
+        case LF_METHOD_V3:
+            printf("\t\tMethod V3: '%s' overloaded=#%d method-list=%x\n",
+                   fieldtype->method_v3.name,
+                   fieldtype->method_v3.count, fieldtype->method_v3.mlist);
+            ptr += 2 + 2 + 4 + (strlen(fieldtype->method_v3.name) + 1);
+            break;
+
+        case LF_STMEMBER_V1:
+            printf("\t\tStatic member V1: '%s' attr:%s type:%x\n",
+                   p_string(&fieldtype->stmember_v1.p_name),
+                   get_attr(fieldtype->stmember_v1.attribute),
+                   fieldtype->stmember_v1.type);
+            ptr += 2 + 2 + 2 + (1 + fieldtype->stmember_v1.p_name.namelen);
+            break;
+
+        case LF_STMEMBER_V2:
+            printf("\t\tStatic member V2: '%s' attr:%s type:%x\n",
+                   p_string(&fieldtype->stmember_v2.p_name),
+                   get_attr(fieldtype->stmember_v2.attribute),
+                   fieldtype->stmember_v2.type);
+            ptr += 2 + 2 + 4 + (1 + fieldtype->stmember_v2.p_name.namelen);
+            break;
+
+        case LF_STMEMBER_V3:
+            printf("\t\tStatic member V3: '%s' attr:%s type:%x\n",
+                   fieldtype->stmember_v3.name,
+                   get_attr(fieldtype->stmember_v3.attribute),
+                   fieldtype->stmember_v3.type);
+            ptr += 2 + 2 + 4 + (strlen(fieldtype->stmember_v3.name) + 1);
+            break;
+
+        case LF_FRIENDFCN_V1:
+            printf("\t\tFriend function V1: '%s' type:%x\n",
+                   p_string(&fieldtype->friendfcn_v1.p_name),
+                   fieldtype->friendfcn_v1.type);
+            break;
+
+        case LF_FRIENDFCN_V2:
+            printf("\t\tFriend function V2: '%s' type:%x\n",
+                   p_string(&fieldtype->friendfcn_v2.p_name),
+                   fieldtype->friendfcn_v2.type);
+            break;
+
+#if 0
+        case LF_FRIENDFCN_V3:
+            printf("\t\tFriend function V3: '%s' type:%x\n",
+                   fieldtype->friendfcn_v3.name,
+                   fieldtype->friendfcn_v3.type);
+            break;
+#endif
+
+        case LF_BCLASS_V1:
+            leaf_len = numeric_leaf(&value, &fieldtype->bclass_v1.offset);
+            printf("\t\tBase class V1: type:%x attr:%s @%d\n",
+                   fieldtype->bclass_v1.type, 
+                   get_attr(fieldtype->bclass_v1.attribute), value);
+            ptr += 2 + 2 + 2 + leaf_len;
+            break;
+
+        case LF_BCLASS_V2:
+            leaf_len = numeric_leaf(&value, &fieldtype->bclass_v2.offset);
+            printf("\t\tBase class V2: type:%x attr:%s @%d\n",
+                   fieldtype->bclass_v2.type, 
+                   get_attr(fieldtype->bclass_v2.attribute), value);
+            ptr += 2 + 2 + 4 + leaf_len;
+            break;
+
+        case LF_VBCLASS_V1:
+        case LF_IVBCLASS_V1:
+            leaf_len = numeric_leaf(&value, &fieldtype->vbclass_v1.vbpoff);
+            printf("\t\t%sirtual base class V1: type:%x (ptr:%x) attr:%s vbpoff:%d ",
+                   (fieldtype->generic.id == LF_VBCLASS_V2) ? "V" : "Indirect v",
+                   fieldtype->vbclass_v1.btype, fieldtype->vbclass_v1.vbtype,
+                   get_attr(fieldtype->vbclass_v1.attribute), value);
+            ptr += 2 + 2 + 2 + 2 + leaf_len;
+            leaf_len = numeric_leaf(&value, (const unsigned short*)ptr);
+            printf("vboff:%d\n", value);
+            ptr += leaf_len;
+            break;
+
+        case LF_VBCLASS_V2:
+        case LF_IVBCLASS_V2:
+            leaf_len = numeric_leaf(&value, &fieldtype->vbclass_v1.vbpoff);
+            printf("\t\t%sirtual base class V2: type:%x (ptr:%x) attr:%s vbpoff:%d ",
+                   (fieldtype->generic.id == LF_VBCLASS_V2) ? "V" : "Indirect v",
+                   fieldtype->vbclass_v2.btype, fieldtype->vbclass_v2.vbtype,
+                   get_attr(fieldtype->vbclass_v2.attribute), value);
+            ptr += 2 + 2 + 4 + 4 + leaf_len;
+            leaf_len = numeric_leaf(&value, (const unsigned short*)ptr);
+            printf("vboff:%d\n", value);
+            ptr += leaf_len;
+            break;
+
+        case LF_FRIENDCLS_V1:
+            printf("\t\tFriend class V1: type:%x\n", fieldtype->friendcls_v1.type);
+            break;
+
+        case LF_FRIENDCLS_V2:
+            printf("\t\tFriend class V2: type:%x\n", fieldtype->friendcls_v2.type);
+            break;
+
+        case LF_NESTTYPE_V1:
+            printf("\t\tNested type V1: '%s' type:%x\n",
+                   p_string(&fieldtype->nesttype_v1.p_name),
+                   fieldtype->nesttype_v1.type);
+            ptr += 2 + 2 + (1 + fieldtype->nesttype_v1.p_name.namelen);
+            break;
+
+        case LF_NESTTYPE_V2:
+            printf("\t\tNested type V2: '%s' pad0:%u type:%x\n",
+                   p_string(&fieldtype->nesttype_v2.p_name),
+                   fieldtype->nesttype_v2._pad0, fieldtype->nesttype_v2.type);
+            ptr += 2 + 2 + 4 + (1 + fieldtype->nesttype_v2.p_name.namelen);
+            break;
+
+        case LF_NESTTYPE_V3:
+            printf("\t\tNested type V3: '%s' pad0:%u type:%x\n",
+                   fieldtype->nesttype_v3.name,
+                   fieldtype->nesttype_v3._pad0, fieldtype->nesttype_v3.type);
+            ptr += 2 + 2 + 4 + (strlen(fieldtype->nesttype_v3.name) + 1);
+            break;
+
+        case LF_VFUNCTAB_V1:
+            printf("\t\tVirtual function table V1: type:%x\n",
+                   fieldtype->vfunctab_v1.type);
+            ptr += 2 + 2;
+            break;
+
+        case LF_VFUNCTAB_V2:
+            printf("\t\tVirtual function table V2: type:%x\n",
+                   fieldtype->vfunctab_v2.type);
+            ptr += 2 + 2 + 4;
+            break;
+
+        case LF_VFUNCOFF_V1:
+            printf("\t\tVirtual function table offset V1: type:%x offset:%x\n",
+                   fieldtype->vfuncoff_v1.type, fieldtype->vfuncoff_v1.offset);
+            break;
+
+        case LF_VFUNCOFF_V2:
+            printf("\t\tVirtual function table offset V2: type:%x offset:%x\n",
+                   fieldtype->vfuncoff_v2.type, fieldtype->vfuncoff_v2.offset);
+            break;
+
+        default:
+            printf(">>> Unsupported field-id %x\n", fieldtype->generic.id);
+            dump_data((const void*)fieldtype, 0x30, "\t");
+            return;
+            break;
+        }
+    }
+}
+
+int codeview_dump_types(const void* table, unsigned long len)
+{
+    unsigned int        curr_type = 0x1000;
+    const unsigned char*ptr = table;
+    int                 i, leaf_len, value;
+    const char*         str;
+
+    while (ptr - (const unsigned char*)table < len)
+    {
+        const union codeview_type* type = (const union codeview_type*)ptr;
+        const union codeview_reftype* reftype = (const union codeview_reftype*)ptr;
+        int retv = TRUE;
+
+        switch (type->generic.id)
+        {
+        case LF_POINTER_V1:
+            printf("\t%x => Pointer V1 to type:%x\n",
+                   curr_type, type->pointer_v1.datatype);
+            break;
+        case LF_POINTER_V2:
+            printf("\t%x => Pointer V2 to type:%x\n",
+                   curr_type, type->pointer_v2.datatype);
+            break;
+        case LF_ARRAY_V1:
+            leaf_len = numeric_leaf(&value, &type->array_v1.arrlen);
+            printf("\t%x => Array V1-'%s'[%u type:%x] type:%x\n",
+                   curr_type, p_string(PSTRING(&type->array_v1.arrlen, leaf_len)),
+                   value, type->array_v1.idxtype, type->array_v1.elemtype);
+            break;
+        case LF_ARRAY_V2:
+            leaf_len = numeric_leaf(&value, &type->array_v2.arrlen);
+            printf("\t%x => Array V2-'%s'[%u type:%x] type:%x\n",
+                   curr_type, p_string(PSTRING(&type->array_v2.arrlen, leaf_len)),
+                   value, type->array_v2.idxtype, type->array_v2.elemtype);
+            break;
+        case LF_ARRAY_V3:
+            leaf_len = numeric_leaf(&value, &type->array_v3.arrlen);
+            str = (const char*)&type->array_v3.arrlen + leaf_len;
+            printf("\t%x => Array V3-'%s'[%u type:%x] type:%x\n",
+                   curr_type, str, value, 
+                   type->array_v3.idxtype, type->array_v3.elemtype);
+            break;
+
+
+        /* a bitfields is a CodeView specific data type which represent a bitfield
+         * in a structure or a class. For now, we store it in a SymTag-like type
+         * (so that the rest of the process is seamless), but check at udt inclusion
+         * type for its presence
+         */
+        case LF_BITFIELD_V1:
+            printf("\t%x => Bitfield V1:%x offset:%u #bits:%u\n",
+                   curr_type, reftype->bitfield_v1.type, reftype->bitfield_v1.bitoff,
+                   reftype->bitfield_v1.nbits);
+            break;
+
+        case LF_BITFIELD_V2:
+            printf("\t%x => Bitfield V2:%x offset:%u #bits:%u\n",
+                   curr_type, reftype->bitfield_v2.type, reftype->bitfield_v2.bitoff,
+                   reftype->bitfield_v2.nbits);
+            break;
+
+        case LF_FIELDLIST_V1:
+        case LF_FIELDLIST_V2:
+            printf("\t%x => Fieldlist\n", curr_type);
+            do_field(reftype->fieldlist.list, ptr + reftype->generic.len + 2);
+            break;
+
+        case LF_STRUCTURE_V1:
+        case LF_CLASS_V1:
+            leaf_len = numeric_leaf(&value, &type->struct_v1.structlen);
+            printf("\t%x => %s V1 '%s' elts:%u prop:%u fieldlist-type:%x derived-type:%x vshape:%x size:%u\n",
+                   curr_type, type->generic.id == LF_CLASS_V1 ? "Class" : "Struct",
+                   p_string(PSTRING(&type->struct_v1.structlen, leaf_len)),
+                   type->struct_v1.n_element, type->struct_v1.property,
+                   type->struct_v1.fieldlist, type->struct_v1.derived, 
+                   type->struct_v1.vshape, value);
+            break;
+
+        case LF_STRUCTURE_V2:
+        case LF_CLASS_V2:
+            leaf_len = numeric_leaf(&value, &type->struct_v2.structlen);
+            printf("\t%x => %s V2 '%s' elts:%u prop:%u\n"
+                   "                fieldlist-type:%x derived-type:%x vshape:%x size:%u\n",
+                   curr_type, type->generic.id == LF_CLASS_V2 ? "Class" : "Struct",
+                   p_string(PSTRING(&type->struct_v2.structlen, leaf_len)),
+                   type->struct_v2.n_element, type->struct_v2.property,
+                   type->struct_v2.fieldlist, type->struct_v2.derived, 
+                   type->struct_v2.vshape, value);
+            break;
+
+        case LF_STRUCTURE_V3:
+        case LF_CLASS_V3:
+            leaf_len = numeric_leaf(&value, &type->struct_v3.structlen);
+            str = (const char*)&type->struct_v3.structlen + leaf_len;
+            printf("\t%x => %s V3 '%s' elts:%u prop:%u\n"
+                   "                fieldlist-type:%x derived-type:%x vshape:%x size:%u\n",
+                   curr_type, type->generic.id == LF_CLASS_V3 ? "Class" : "Struct",
+                   str, type->struct_v3.n_element, type->struct_v3.property,
+                   type->struct_v3.fieldlist, type->struct_v3.derived, 
+                   type->struct_v3.vshape, value);
+            break;
+
+        case LF_UNION_V1:
+            leaf_len = numeric_leaf(&value, &type->union_v1.un_len);
+            printf("\t%x => Union V1 '%s' count:%u prop:%u fieldlist-type:%x size:%u\n",
+                   curr_type, p_string(PSTRING(&type->union_v1.un_len, leaf_len)),
+                   type->union_v1.count, type->union_v1.property,
+                   type->union_v1.fieldlist, value);
+            break;
+
+        case LF_UNION_V2:
+            leaf_len = numeric_leaf(&value, &type->union_v2.un_len);
+            printf("\t%x => Union V2 '%s' count:%u prop:%u fieldlist-type:%x size:%u\n",
+                   curr_type, p_string(PSTRING(&type->union_v2.un_len, leaf_len)),
+                   type->union_v2.count, type->union_v2.property,
+                   type->union_v2.fieldlist, value);
+            break;
+
+        case LF_UNION_V3:
+            leaf_len = numeric_leaf(&value, &type->union_v3.un_len);
+            str = (const char*)&type->union_v3.un_len + leaf_len;
+            printf("\t%x => Union V3 '%s' count:%u prop:%u fieldlist-type:%x size:%u\n",
+                   curr_type, str, type->union_v3.count, 
+                   type->union_v3.property, type->union_v3.fieldlist, value);
+            break;
+
+        case LF_ENUM_V1:
+            printf("\t%x => Enum V1 '%s' type:%x field-type:%x count:%u property:%x\n",
+                   curr_type, p_string(&type->enumeration_v1.p_name),
+                   type->enumeration_v1.type,
+                   type->enumeration_v1.fieldlist,
+                   type->enumeration_v1.count,
+                   type->enumeration_v1.property);
+            break;
+
+        case LF_ENUM_V2:
+            printf("\t%x => Enum V2 '%s' type:%x field-type:%x count:%u property:%x\n",
+                   curr_type, p_string(&type->enumeration_v2.p_name),
+                   type->enumeration_v2.type,
+                   type->enumeration_v2.fieldlist,
+                   type->enumeration_v2.count,
+                   type->enumeration_v2.property);
+            break;
+
+        case LF_ENUM_V3:
+            printf("\t%x => Enum V3 '%s' type:%x field-type:%x count:%u property:%x\n",
+                   curr_type, type->enumeration_v3.name, 
+                   type->enumeration_v3.type,
+                   type->enumeration_v3.fieldlist,
+                   type->enumeration_v3.count,
+                   type->enumeration_v3.property);
+            break;
+
+        case LF_ARGLIST_V1:
+            printf("\t%x => Arglist V1(#%u):", curr_type, reftype->arglist_v1.num);
+            for (i = 0; i < reftype->arglist_v1.num; i++)
+            {
+                printf(" %x", reftype->arglist_v1.args[i]);
+            }
+            printf("\n");
+            break;
+
+        case LF_ARGLIST_V2:
+            printf("\t%x => Arglist V2(#%u):", curr_type, reftype->arglist_v2.num);
+            for (i = 0; i < reftype->arglist_v2.num; i++)
+            {
+                printf("\t %x", reftype->arglist_v2.args[i]);
+            }
+            printf("\t\n");
+            break;
+
+        case LF_PROCEDURE_V1:
+            /* FIXME: unknown could be the calling convention for the proc */
+            printf("\t%x => Procedure V1 ret_type:%x call:%x (#%u args_type:%x)\n",
+                   curr_type, type->procedure_v1.rvtype,
+                   type->procedure_v1.call, type->procedure_v1.params,
+                   type->procedure_v1.arglist);
+            break;
+        case LF_PROCEDURE_V2:
+            printf("\t%x => Procedure V2 ret_type:%x unk:%x (#%u args_type:%x)\n",
+                   curr_type, type->procedure_v2.rvtype,
+                   type->procedure_v2.call, type->procedure_v2.params,
+                   type->procedure_v2.arglist);
+            break;
+
+        case LF_MFUNCTION_V2:
+            printf("\t%x => MFunction V2 ret-type:%x call:%x class-type:%x this-type:%x\n"
+                   "\t\t#args:%x args-type:%x this_adjust:%x\n",
+                   curr_type,
+                   type->mfunction_v2.rvtype,
+                   type->mfunction_v2.call,
+                   type->mfunction_v2.class_type,
+                   type->mfunction_v2.this_type,
+                   type->mfunction_v2.params,
+                   type->mfunction_v2.arglist, 
+                   type->mfunction_v2.this_adjust);
+            break;
+
+        case LF_MODIFIER_V1:
+            printf("\t%x => Modifier V1 type:%x modif:%x\n",
+                   curr_type, type->modifier_v1.type, type->modifier_v1.attribute);
+            break;
+        case LF_MODIFIER_V2:
+            printf("\t%x => Modifier V2 type:%x modif:%x\n",
+                   curr_type, type->modifier_v2.type, type->modifier_v2.attribute);  
+            break;
+
+        case LF_METHODLIST_V1:
+            {
+                unsigned short* pattr = (unsigned short*)((const char*)type + 4);
+                
+                printf("\t%x => Method list\n", curr_type);
+                while ((const char*)pattr < (const char*)type + type->generic.len + 2)
+                {
+                    switch ((*pattr >> 2) & 7)
+                    {
+                    case 4: case 6:
+                        printf("\t\t\tattr:%s type:%x vtab-offset:%x\n",
+                               get_attr(pattr[0]), pattr[1],
+                               *(unsigned*)(&pattr[2]));
+                        pattr += 3;
+                        break;
+                    default:
+                        printf("\t\t\tattr:%s type:%x\n",
+                               get_attr(pattr[0]), pattr[1]);
+                        pattr += 2;
+                    }
+                }
+            }
+            break;
+
+        case LF_METHODLIST_V2:
+            {
+                unsigned* pattr = (unsigned*)((const char*)type + 4);
+                
+                printf("\t%x => Method list\n", curr_type);
+                while ((const char*)pattr < (const char*)type + type->generic.len + 2)
+                {
+                    switch ((*pattr >> 2) & 7)
+                    {
+                    case 4: case 6:
+                        printf("\t\t\tattr:%s type:%x vtab-offset:%x\n",
+                               get_attr(pattr[0]), pattr[1], pattr[2]);
+                        pattr += 3;
+                        break;
+                    default:
+                        printf("\t\t\tattr:%s type:%x\n",
+                               get_attr(pattr[0]), pattr[1]);
+                        pattr += 2;
+                    }
+                }
+            }
+            break;
+
+        case LF_VTSHAPE_V1:
+            {
+                int count = *(unsigned short*)((const char*)type + 4);
+                int shift = 0;
+                const char* ptr = (const char*)type + 6;
+                const char* desc[] = {"Near", "Far", "Thin", "Disp to outtermost",
+                                      "Pointer to metaclass", "Near32", "Far32"};
+                printf("\t%x => VT Shape #%d: ", curr_type, count);
+                while (count--)
+                {
+                    if (((*ptr << shift) & 0xF) <= 6)
+                        printf("%s ", desc[(*ptr << shift) & 0xF]);
+                    else
+                        printf("%x ", (*ptr << shift) & 0xF);
+                    if (shift == 0) shift = 4; else {shift = 0; ptr++;}
+                }
+                printf("\n");
+            }
+            break;
+
+        default:
+            printf(">>> Unsupported type-id %x for %x\n", type->generic.id, curr_type);
+            dump_data((const void*)type, type->generic.len + 2, "");
+            break;
+        }
+
+        if (!retv)
+            return FALSE;
+
+        curr_type++;
+        ptr += type->generic.len + 2;
+    }
+
+    return TRUE;
+}
+
+int codeview_dump_symbols(const void* root, unsigned long size)
+{
+    int                                 i, length;
+    const char*                         curr_func = NULL;
+    int         nest_block = 0;
+    /*
+     * Loop over the different types of records and whenever we
+     * find something we are interested in, record it and move on.
+     */
+    for (i = 0; i < size; i += length)
+    {
+        const union codeview_symbol* sym = (const union codeview_symbol*)((const char*)root + i);
+        length = sym->generic.len + 2;
+        if (!sym->generic.id || length < 4) break;
+        switch (sym->generic.id)
+        {
+        /*
+         * Global and local data symbols.  We don't associate these
+         * with any given source file.
+         */
+	case S_GDATA_V2:
+	case S_LDATA_V2:
+            printf("\tS-%s-Data V2 '%s' %04x:%08x type:%08x\n", 
+                   sym->generic.id == S_GDATA_V2 ? "Global" : "Local",
+                   p_string(&sym->data_v2.p_name),
+                   sym->data_v2.segment, sym->data_v2.offset, sym->data_v2.symtype);
+	    break;
+
+        case S_LDATA_V3:
+        case S_GDATA_V3:
+/* EPP         case S_DATA_V3: */
+            printf("\tS-%s-Data V3 '%s' (%04x:%08x) type:%08x\n",
+                   sym->generic.id == S_GDATA_V3 ? "Global" : "Local",
+                   sym->data_v3.name, 
+                   sym->data_v3.segment, sym->data_v3.offset, 
+                   sym->data_v3.symtype);
+            break;
+
+	case S_PUB_V2:
+            printf("\tS-Public V2 '%s' %04x:%08x type:%08x\n",
+                   p_string(&sym->public_v2.p_name),
+                   sym->public_v2.segment, sym->public_v2.offset,
+                   sym->public_v2.symtype);
+	    break;
+
+	case S_PUB_V3:
+        /* not completly sure of those two anyway */
+	case S_PUB_FUNC1_V3:
+	case S_PUB_FUNC2_V3:
+            printf("\tS-Public%s V3 '%s' %04x:%08x type:%08x\n",
+                   sym->generic.id == S_PUB_V3 ? "" :
+                                      (sym->generic.id == S_PUB_FUNC1_V3 ? "<subkind1" : "<subkind2"),
+                   sym->public_v3.name,
+                   sym->public_v3.segment,
+                   sym->public_v3.offset, sym->public_v3.symtype);
+	    break;
+
+        /*
+         * Sort of like a global function, but it just points
+         * to a thunk, which is a stupid name for what amounts to
+         * a PLT slot in the normal jargon that everyone else uses.
+         */
+	case S_THUNK_V1:
+            printf("\tS-Thunk V1 '%s' (%04x:%08x#%x) type:%x\n", 
+                   p_string(&sym->thunk_v1.p_name),
+                   sym->thunk_v1.segment, sym->thunk_v1.offset,
+                   sym->thunk_v1.thunk_len, sym->thunk_v1.thtype);
+            curr_func = strdup(p_string(&sym->thunk_v1.p_name));
+	    break;
+
+	case S_THUNK_V3:
+            printf("\tS-Thunk V3 '%s' (%04x:%08x#%x) type:%x\n", 
+                   sym->thunk_v3.name,
+                   sym->thunk_v3.segment, sym->thunk_v3.offset,
+                   sym->thunk_v3.thunk_len, sym->thunk_v3.thtype);
+            curr_func = strdup(sym->thunk_v3.name);
+	    break;
+
+        /* Global and static functions */
+	case S_GPROC_V1:
+	case S_LPROC_V1:
+            printf("\tS-%s-Proc V1: '%s' (%04x:%08x#%x) type:%x\n",
+                   sym->generic.id == S_GPROC_V1 ? "Global" : "-Local",
+                   p_string(&sym->proc_v1.p_name),
+                   sym->proc_v1.segment, sym->proc_v1.offset,
+                   sym->proc_v1.proc_len, sym->proc_v1.proctype);
+            if (nest_block)
+            {
+                printf(">>> prev func '%s' still has nest_block %u count\n", curr_func, nest_block);
+                nest_block = 0;
+            }
+            curr_func = strdup(p_string(&sym->proc_v1.p_name));
+/* EPP 	unsigned int	pparent; */
+/* EPP 	unsigned int	pend; */
+/* EPP 	unsigned int	next; */
+/* EPP 	unsigned int	debug_start; */
+/* EPP 	unsigned int	debug_end; */
+/* EPP 	unsigned char	flags; */
+	    break;
+
+	case S_GPROC_V2:
+	case S_LPROC_V2:
+            printf("\tS-%s-Proc V2: '%s' (%04x:%08x#%x) type:%x\n",
+                   sym->generic.id == S_GPROC_V2 ? "Global" : "-Local",
+                   p_string(&sym->proc_v2.p_name),
+                   sym->proc_v2.segment, sym->proc_v2.offset,
+                   sym->proc_v2.proc_len, sym->proc_v2.proctype);
+            if (nest_block)
+            {
+                printf(">>> prev func '%s' still has nest_block %u count\n", curr_func, nest_block);
+                nest_block = 0;
+            }
+            curr_func = strdup(p_string(&sym->proc_v2.p_name));
+/* EPP 	unsigned int	pparent; */
+/* EPP 	unsigned int	pend; */
+/* EPP 	unsigned int	next; */
+/* EPP 	unsigned int	debug_start; */
+/* EPP 	unsigned int	debug_end; */
+/* EPP 	unsigned char	flags; */
+	    break;
+
+        case S_LPROC_V3:
+        case S_GPROC_V3:
+            printf("\tS-%s-Procedure V3 '%s' (%04x:%08x#%x) type:%x\n",
+                   sym->generic.id == S_GPROC_V3 ? "Global" : "Local",
+                   sym->proc_v3.name,
+                   sym->proc_v3.segment, sym->proc_v3.offset,
+                   sym->proc_v3.proc_len, sym->proc_v3.proctype);
+            if (nest_block)
+            {
+                printf(">>> prev func '%s' still has nest_block %u count\n", curr_func, nest_block);
+                nest_block = 0;
+            }
+            curr_func = strdup(sym->proc_v3.name);
+/* EPP 	unsigned int	pparent; */
+/* EPP 	unsigned int	pend; */
+/* EPP 	unsigned int	next; */
+/* EPP 	unsigned int	debug_start; */
+/* EPP 	unsigned int	debug_end; */
+/* EPP 	unsigned char	flags; */
+            break;
+
+        /* Function parameters and stack variables */
+	case S_BPREL_V1:
+            printf("\tS-BP-relative V1: '%s' @%d type:%x (%s)\n", 
+                   p_string(&sym->stack_v1.p_name),
+                   sym->stack_v1.offset, sym->stack_v1.symtype, curr_func);
+            break;
+
+	case S_BPREL_V2:
+            printf("\tS-BP-relative V2: '%s' @%d type:%x (%s)\n", 
+                   p_string(&sym->stack_v2.p_name),
+                   sym->stack_v2.offset, sym->stack_v2.symtype, curr_func);
+            break;
+
+        case S_BPREL_V3:
+            printf("\tS-BP-relative V3: '%s' @%d type:%x (in %s)\n", 
+                   sym->stack_v3.name, sym->stack_v3.offset,
+                   sym->stack_v3.symtype, curr_func);
+            break;
+
+        case S_REGISTER_V1:
+            printf("\tS-Register V1 '%s' in %s type:%x register:%x\n",
+                   p_string(&sym->register_v1.p_name),
+                   curr_func, sym->register_v1.reg, sym->register_v1.type);
+            break;
+
+        case S_REGISTER_V2:
+            printf("\tS-Register V2 '%s' in %s type:%x register:%x\n",
+                   p_string(&sym->register_v2.p_name),
+                   curr_func, sym->register_v2.reg, sym->register_v2.type);
+            break;
+
+        case S_REGISTER_V3:
+            printf("\tS-Register V3 '%s' in %s type:%x register:%x\n",
+                   sym->register_v3.name,
+                   curr_func, sym->register_v3.reg, sym->register_v3.type);
+            break;
+
+        case S_BLOCK_V1:
+            printf("\tS-Block V1 '%s' in '%s' (%04x:%08x#%08x)\n",
+                   p_string(&sym->block_v1.p_name),
+                   curr_func, 
+                   sym->block_v1.segment, sym->block_v1.offset,
+                   sym->block_v1.length);
+            nest_block++;
+            break;
+
+        case S_BLOCK_V3:
+            printf("\tS-Block V3 '%s' in '%s' (%04x:%08x#%08x) parent:%u end:%x\n",
+                   sym->block_v3.name, curr_func, 
+                   sym->block_v3.segment, sym->block_v3.offset, sym->block_v3.length,
+                   sym->block_v3.parent, sym->block_v3.end);
+            nest_block++;
+            break;
+
+        case S_END_V1:
+            if (nest_block)
+            {
+                nest_block--;
+                printf("\tS-End-Of block (%u)\n", nest_block);
+            }
+            else
+            {
+                printf("\tS-End-Of %s\n", curr_func);
+                free((void*)curr_func);
+                curr_func = NULL;
+            }
+            break;
+
+        case S_COMPILAND_V1:
+            {
+                const char*     machine;
+                const char*     lang;
+
+                switch (sym->compiland_v1.unknown & 0xFF)
+                {
+                case 0x00:      machine = "Intel 8080"; break;
+                case 0x01:      machine = "Intel 8086"; break;
+                case 0x02:      machine = "Intel 80286"; break;
+                case 0x03:      machine = "Intel 80386"; break;
+                case 0x04:      machine = "Intel 80486"; break;
+                case 0x05:      machine = "Intel Pentium"; break;
+                case 0x10:      machine = "MIPS R4000"; break;
+                default:
+                    {
+                        static char tmp[16];
+                        sprintf(tmp, "machine=%x", sym->compiland_v1.unknown & 0xFF);
+                        machine = tmp;
+                    }
+                    break;
+                }
+                switch ((sym->compiland_v1.unknown >> 8) & 0xFF)
+                {
+                case 0x00:      lang = "C"; break;
+                case 0x01:      lang = "C++"; break;
+                case 0x02:      lang = "Fortran"; break;
+                case 0x03:      lang = "Masm"; break;
+                case 0x04:      lang = "Pascal"; break;
+                case 0x05:      lang = "Basic"; break;
+                case 0x06:      lang = "Cobol"; break;
+                default:
+                    {
+                        static char tmp[16];
+                        sprintf(tmp, "language=%x", (sym->compiland_v1.unknown >> 8) & 0xFF);
+                        lang = tmp;
+                    }
+                    break;
+                }
+
+                printf("\tS-Compiland V1 '%s' %s %s unk:%x\n",
+                       p_string(&sym->compiland_v1.p_name), machine, lang,
+                       sym->compiland_v1.unknown >> 16);
+            }
+            break;
+
+        case S_COMPILAND_V2:
+            printf("\tS-Compiland V2 '%s'\n",
+                   p_string(&sym->compiland_v2.p_name));
+            dump_data((const void*)sym, sym->generic.len + 2, "  ");
+            {
+                const char* ptr = sym->compiland_v2.p_name.name + sym->compiland_v2.p_name.namelen;
+                while (*ptr)
+                {
+                    printf("\t\t%s => ", ptr); ptr += strlen(ptr) + 1;
+                    printf("%s\n", ptr); ptr += strlen(ptr) + 1;
+                }
+            }
+            break;
+
+        case S_COMPILAND_V3:
+            printf("\tS-Compiland V3 '%s' unknown:%x\n",
+                   sym->compiland_v3.name, sym->compiland_v3.unknown);
+            break;
+
+        case S_OBJNAME_V1:
+            printf("\tS-ObjName V1 sig:%.4s '%s'\n",
+                   sym->objname_v1.signature, p_string(&sym->objname_v1.p_name));
+            break;
+
+        case S_LABEL_V1:
+            printf("\tS-Label V1 '%s' in '%s' (%04x:%08x)\n", 
+                   p_string(&sym->label_v1.p_name),     
+                   curr_func, sym->label_v1.segment, sym->label_v1.offset);
+            break;
+
+        case S_LABEL_V3:
+            printf("\tS-Label V3 '%s' in '%s' (%04x:%08x) flag:%x\n", 
+                   sym->label_v3.name, curr_func, sym->label_v3.segment,
+                   sym->label_v3.offset, sym->label_v3.flags);
+            break;
+
+        case S_CONSTANT_V2:
+            {
+                int             val, vlen;
+
+                vlen = numeric_leaf(&val, &sym->constant_v2.cvalue);
+                printf("\tS-Constant V2 '%s' = %u type:%x\n", 
+                       p_string(PSTRING(&sym->constant_v2.cvalue, vlen)), val, sym->constant_v2.type);
+            }
+            break;
+
+        case S_CONSTANT_V3:
+            {
+                int             val, vlen;
+
+                vlen = numeric_leaf(&val, &sym->constant_v3.cvalue);
+                printf("\tS-Constant V3 '%s' = %u type:%x\n",
+                       (const char*)&sym->constant_v3.cvalue + vlen,
+                       val, sym->constant_v3.type);
+            }
+            break;
+
+        case S_UDT_V1:
+            printf("\tS-Udt V1 '%s': type:0x%x\n", 
+                   p_string(&sym->udt_v1.p_name), sym->udt_v1.type);
+            break;
+
+        case S_UDT_V2:
+            printf("\tS-Udt V2 '%s': type:0x%x\n", 
+                   p_string(&sym->udt_v2.p_name), sym->udt_v2.type);
+            break;
+
+        case S_UDT_V3:
+            printf("\tS-Udt V3 '%s': type:0x%x\n",
+                   sym->udt_v3.name, sym->udt_v3.type);
+            break;
+        /*
+         * These are special, in that they are always followed by an
+         * additional length-prefixed string which is *not* included
+         * into the symbol length count.  We need to skip it.
+         */
+	case S_PROCREF_V1:
+            printf("\tS-Procref V1 "); goto doaref;
+	case S_DATAREF_V1:
+            printf("\tS-Dataref V1 "); goto doaref;
+	case S_LPROCREF_V1:
+            printf("\tS-L-Procref V1 "); goto doaref;
+        doaref:
+            {
+                const struct p_string* pname;
+
+                pname = PSTRING(sym, length);
+                length += (pname->namelen + 1 + 3) & ~3;
+                printf("\t%08x %08x %08x '%s'\n",      
+                       *(((DWORD*)sym) + 1), *(((DWORD*)sym) + 2), *(((DWORD*)sym) + 3), 
+                       p_string(pname));
+            }
+            break;
+        case S_MSTOOL_V3:    /* info about tool used to create CU */
+            {
+                const unsigned short*     ptr = ((const unsigned short*)sym) + 2;
+
+                /* FIXME: what are all those values for ? */
+                printf("\tTool V3 ??? %x-%x-%x-%x-%x-%x-%x-%x-%x %s\n", 
+                       ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7], 
+                       ptr[8], (char*)(&ptr[9]));
+                dump_data((const void*)sym, sym->generic.len + 2, "\t\t");
+            }
+            break;
+
+        default:
+            printf(">>> Unsupported symbol-id %x sz=%d\n", sym->generic.id, sym->generic.len + 2);
+            dump_data((const void*)sym, sym->generic.len + 2, "  ");
+        }
+    }
+    return 0;
+}
diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c
index 6beb997..0310ab7 100644
--- a/tools/winedump/pdb.c
+++ b/tools/winedump/pdb.c
@@ -286,12 +286,12 @@ static void pdb_dump_symbols(struct pdb_
 
     /* Read global symbol table */
     modimage = reader->read_file(reader, symbols->gsym_file);
-/* EPP     if (modimage) */
-/* EPP     { */
-/* EPP         printf("\t------------globals-------------\n"); */
-/* EPP         codeview_dump_symbols(modimage, pdb_get_file_size(reader, symbols->gsym_file)); */
-/* EPP         free((char*)modimage); */
-/* EPP     }  */
+    if (modimage)
+    {
+        printf("\t------------globals-------------\n"); 
+        codeview_dump_symbols(modimage, pdb_get_file_size(reader, symbols->gsym_file));
+        free((char*)modimage);
+    }
 
     /* Read per-module symbol / linenumber tables */
     file = (const char*)symbols + sizeof(PDB_SYMBOLS);
@@ -307,7 +307,39 @@ static void pdb_dump_symbols(struct pdb_
             file_name   = sym_file->filename;
             symbol_size = sym_file->symbol_size;
             lineno_size = sym_file->lineno_size;
-            printf("\tgot symbol_file %s (SIMPLE)\n", file_name);
+            printf("\t--------symbol file----------- %s\n", file_name);
+            printf("\tgot symbol_file\n"
+                   "\t\tunknown1:   %08x \n"
+                   "\t\trange\n"
+                   "\t\t\tsegment:         %04x\n"
+                   "\t\t\tpad1:            %04x\n"
+                   "\t\t\toffset:          %08x\n"
+                   "\t\t\tsize:            %08x\n"
+                   "\t\t\tcharacteristics: %08x\n"
+                   "\t\t\tindex:           %04x\n"
+                   "\t\t\tpad2:            %04x\n"
+                   "\t\tflag:       %04x\n"
+                   "\t\tfile:       %04x\n"
+                   "\t\tsymb size:  %08x\n"
+                   "\t\tline size:  %08x\n"
+                   "\t\tunknown2:   %08x\n"
+                   "\t\tnSrcFiles:  %08x\n"
+                   "\t\tattribute:  %08x\n",
+                   sym_file->unknown1,
+                   sym_file->range.segment,
+                   sym_file->range.pad1,
+                   sym_file->range.offset,
+                   sym_file->range.size,
+                   sym_file->range.characteristics,
+                   sym_file->range.index,
+                   sym_file->range.pad2,
+                   sym_file->flag,
+                   sym_file->file,
+                   sym_file->symbol_size,
+                   sym_file->lineno_size,
+                   sym_file->unknown2,
+                   sym_file->nSrcFiles,
+                   sym_file->attribute);
         }
         else
         {
@@ -316,8 +348,8 @@ static void pdb_dump_symbols(struct pdb_
             file_name   = sym_file->filename;
             symbol_size = sym_file->symbol_size;
             lineno_size = sym_file->lineno_size;
-            printf("\tgot symbol_file_ex %s\n"
-                   "\t\tunknown1:   %08x \n"
+            printf("\t--------symbol file----------- %s\n", file_name);
+            printf("\t\tunknown1:   %08x \n"
                    "\t\trange\n"
                    "\t\t\tsegment:         %04x\n"
                    "\t\t\tpad1:            %04x\n"
@@ -337,7 +369,6 @@ static void pdb_dump_symbols(struct pdb_
                    "\t\tattribute:  %08x\n"
                    "\t\treserved/0: %08x\n"
                    "\t\treserved/1: %08x\n",
-                   sym_file->filename,
                    sym_file->unknown1,
                    sym_file->range.segment,
                    sym_file->range.pad1,
@@ -362,15 +393,13 @@ static void pdb_dump_symbols(struct pdb_
         if (modimage)
         {
             int total_size = pdb_get_file_size(reader, file_nr);
-            printf("\t------------module-------------\n");
-            dump_data(modimage, total_size, "");
-            printf("\t\tGot module: size:%08x symbol:%08x(%08x) lineno:%08x(%08x)\n",
-                   total_size, symbol_size, symbol_size, lineno_size, symbol_size + lineno_size);
-            /* what's that ??? */
-            dump_data(modimage + symbol_size + lineno_size, total_size - (symbol_size + lineno_size), "\t\t\t");
-/* EPP                 if (symbol_size) */
-/* EPP                     codeview_snarf((const char*)modimage + sizeof(DWORD), symbol_size); */
+
+            if (symbol_size)
+                codeview_dump_symbols((const char*)modimage + sizeof(DWORD), symbol_size);
                 
+            /* what's that part ??? */
+            if (0)
+                dump_data(modimage + symbol_size + lineno_size, total_size - (symbol_size + lineno_size), "\t\t\t");
             free((char*)modimage);
         }
             
@@ -429,7 +458,7 @@ static void pdb_dump_types(struct pdb_re
            types->search_len,
            types->unknown_offset,
            types->unknown_len);
-/* codeview_parse_type_table((const char*)types + types->type_offset, types->type_size); */
+    codeview_dump_types((const char*)types + types->type_offset, types->type_size);
     free((char*)types);
 }
 
diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h
index f7385e8..0d2a051 100644
--- a/tools/winedump/winedump.h
+++ b/tools/winedump/winedump.h
@@ -247,6 +247,8 @@ enum FileSig    get_kind_emf(void);
 void            emf_dump( void );
 enum FileSig    get_kind_pdb(void);
 void            pdb_dump(void);
+int             codeview_dump_symbols(const void* root, unsigned long size);
+int             codeview_dump_types(const void* table, unsigned long len);
 
 void            dump_stabs(const void* pv_stabs, unsigned szstabs, const char* stabstr, unsigned szstr);
 void		dump_codeview(unsigned long ptr, unsigned long len);



More information about the wine-patches mailing list