[PATCH] [WineDump, DbgHelp]: in .pdb files (>= VC2005), handle the case where the codeview_linetab2_file structure is not the first one

Eric Pouech eric.pouech at orange.fr
Sat Oct 31 08:57:40 CDT 2009




A+
---

 dlls/dbghelp/msc.c     |   82 +++++++++++++++++++++++++++++++-----------------
 include/wine/mscvpdb.h |   47 +++++++++++++++++++---------
 tools/winedump/msc.c   |   74 +++++++++++++++++++++++++++++--------------
 3 files changed, 136 insertions(+), 67 deletions(-)


diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c
index 2932d26..d31dd71 100644
--- a/dlls/dbghelp/msc.c
+++ b/dlls/dbghelp/msc.c
@@ -1362,48 +1362,72 @@ static void codeview_snarf_linetab(const struct msc_debug_info* msc_dbg, const B
 }
 
 static void codeview_snarf_linetab2(const struct msc_debug_info* msc_dbg, const BYTE* linetab, DWORD size,
-                                     const char* strimage, DWORD strsize)
+                                    const char* strimage, DWORD strsize)
 {
-    DWORD       offset;
     unsigned    i;
     DWORD       addr;
-    const struct codeview_linetab2_block* lbh;
-    const struct codeview_linetab2_file* fd;
+    const struct codeview_linetab2*     lt2;
+    const struct codeview_linetab2*     lt2_files = NULL;
+    const struct codeview_lt2blk_lines* lines_blk;
+    const struct codeview_linetab2_file*fd;
     unsigned    source;
     struct symt_function* func;
 
-    if (*(const DWORD*)linetab != 0x000000f4) return;
-    offset = *((const DWORD*)linetab + 1);
-
-    for (lbh = (const struct codeview_linetab2_block*)(linetab + 8 + offset);
-         (const BYTE*)lbh < linetab + size;
-         lbh = (const struct codeview_linetab2_block*)((const char*)lbh + 8 + lbh->size_of_block))
+    /* locate LT2_FILES_BLOCK (if any) */
+    lt2 = (const struct codeview_linetab2*)linetab;
+    while ((const BYTE*)(lt2 + 1) < linetab + size)
     {
-        if (lbh->header != 0x000000f2)
-        /* FIXME: should also check that whole lbh fits in linetab + size */
+        if (lt2->header == LT2_FILES_BLOCK)
         {
-            TRACE("block end %x\n", lbh->header);
+            lt2_files = lt2;
             break;
         }
-        addr = codeview_get_address(msc_dbg, lbh->seg, lbh->start);
-        TRACE("block from %04x:%08x #%x (%x lines)\n",
-               lbh->seg, lbh->start, lbh->size, lbh->nlines);
-        fd = (const struct codeview_linetab2_file*)(linetab + 8 + lbh->file_offset);
-        /* FIXME: should check that string is within strimage + strsize */
-        source = source_new(msc_dbg->module, NULL, strimage + fd->offset);
-        func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr);
-        /* FIXME: at least labels support line numbers */
-        if (!func || func->symt.tag != SymTagFunction)
+        lt2 = codeview_linetab2_next_block(lt2);
+    }
+    if (!lt2_files)
+    {
+        TRACE("No LT2_FILES_BLOCK found\n");
+        return;
+    }
+
+    lt2 = (const struct codeview_linetab2*)linetab;
+    while ((const BYTE*)(lt2 + 1) < linetab + size)
+    {
+        /* FIXME: should also check that whole lines_blk fits in linetab + size */
+        switch (lt2->header)
         {
-            WARN("--not a func at %04x:%08x %x tag=%d\n",
-                 lbh->seg, lbh->start, addr, func ? func->symt.tag : -1);
+        case LT2_LINES_BLOCK:
+            lines_blk = (const struct codeview_lt2blk_lines*)lt2;
+            /* FIXME: should check that file_offset is within the LT2_FILES_BLOCK we've seen */
+            addr = codeview_get_address(msc_dbg, lines_blk->seg, lines_blk->start);
+            TRACE("block from %04x:%08x #%x (%x lines)\n",
+                  lines_blk->seg, lines_blk->start, lines_blk->size, lines_blk->nlines);
+            fd = (const struct codeview_linetab2_file*)((const char*)lt2_files + 8 + lines_blk->file_offset);
+            /* FIXME: should check that string is within strimage + strsize */
+            source = source_new(msc_dbg->module, NULL, strimage + fd->offset);
+            func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr);
+            /* FIXME: at least labels support line numbers */
+            if (!func || func->symt.tag != SymTagFunction)
+            {
+                WARN("--not a func at %04x:%08x %x tag=%d\n",
+                     lines_blk->seg, lines_blk->start, addr, func ? func->symt.tag : -1);
+                break;
+            }
+            for (i = 0; i < lines_blk->nlines; i++)
+            {
+                symt_add_func_line(msc_dbg->module, func, source,
+                                   lines_blk->l[i].lineno ^ 0x80000000,
+                                   lines_blk->l[i].offset - lines_blk->start);
+            }
+            break;
+        case LT2_FILES_BLOCK: /* skip */
+            break;
+        default:
+            TRACE("Block end %x\n", lt2->header);
+            lt2 = (const struct codeview_linetab2*)((const char*)linetab + size);
             continue;
         }
-        for (i = 0; i < lbh->nlines; i++)
-        {
-            symt_add_func_line(msc_dbg->module, func, source,
-                               lbh->l[i].lineno ^ 0x80000000, lbh->l[i].offset - lbh->start);
-        }
+        lt2 = codeview_linetab2_next_block(lt2);
     }
 }
 
diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h
index 9d52a65..2aefa87 100644
--- a/include/wine/mscvpdb.h
+++ b/include/wine/mscvpdb.h
@@ -1642,14 +1642,28 @@ struct startend
     unsigned int	        end;
 };
 
+#define LT2_LINES_BLOCK 0x000000f2
+#define LT2_FILES_BLOCK 0x000000f4
+
 /* there's a new line tab structure from MS Studio 2005 and after
- * it's made of:
- * DWORD        000000f4
- * DWORD        lineblk_offset (counting bytes after this field)
- * an array of codeview_linetab2_file structures
- * an array (starting at <lineblk_offset>) of codeview_linetab2_block structures
+ * it's made of a list of codeview_linetab2 blocks.
+ * We've only seen (so far) list with a single LT2_FILES_BLOCK and several
+ * LT2_LINES_BLOCK. The LT2_FILES block has been encountered either as first
+ * or last block of the list.
+ * A LT2_FILES contains one or several codeview_linetab2_file:s
  */
 
+struct codeview_linetab2
+{
+    DWORD       header;
+    DWORD       size_of_block;
+};
+
+static inline const struct codeview_linetab2* codeview_linetab2_next_block(const struct codeview_linetab2* lt2)
+{
+    return (const struct codeview_linetab2*)((const char*)(lt2 + 1) + lt2->size_of_block);
+}
+
 struct codeview_linetab2_file
 {
     DWORD       offset;         /* offset in string table for filename */
@@ -1658,16 +1672,21 @@ struct codeview_linetab2_file
     WORD        pad0;           /* always 0 */
 };
 
-struct codeview_linetab2_block
+struct codeview_lt2blk_files
+{
+    struct codeview_linetab2            lt2;    /* LT2_FILES */
+    struct codeview_linetab2_file       file[1];
+};
+
+struct codeview_lt2blk_lines
 {
-    DWORD       header;         /* 0x000000f2 */
-    DWORD       size_of_block;  /* next block is at # bytes after this field */
-    DWORD       start;          /* start address of function with line numbers */
-    DWORD       seg;            /* segment of function with line numbers */
-    DWORD       size;           /* size of function with line numbers */
-    DWORD       file_offset;    /* offset for accessing corresponding codeview_linetab2_file */
-    DWORD       nlines;         /* number of lines in this block */
-    DWORD       size_lines;     /* number of bytes following for line number information */
+    struct codeview_linetab2    lt2;            /* LT2_LINE_BLOCK */
+    DWORD                       start;          /* start address of function with line numbers */
+    DWORD                       seg;            /* segment of function with line numbers */
+    DWORD                       size;           /* size of function with line numbers */
+    DWORD                       file_offset;    /* offset for accessing corresponding codeview_linetab2_file */
+    DWORD                       nlines;         /* number of lines in this block */
+    DWORD                       size_lines;     /* number of bytes following for line number information */
     struct {
         DWORD   offset;         /* offset (from <seg>:<start>) for line number */
         DWORD   lineno;         /* the line number (OR:ed with 0x80000000 why ???) */
diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c
index b029852..95cc251 100644
--- a/tools/winedump/msc.c
+++ b/tools/winedump/msc.c
@@ -1417,36 +1417,62 @@ void codeview_dump_linetab(const char* linetab, DWORD size, BOOL pascal_str, con
 
 void codeview_dump_linetab2(const char* linetab, DWORD size, const char* strimage, DWORD strsize, const char* pfx)
 {
-    DWORD       offset;
     unsigned    i;
-    const struct codeview_linetab2_block* lbh;
-    const struct codeview_linetab2_file* fd;
-
-    if (*(const DWORD*)linetab != 0x000000f4) return;
-    offset = *((const DWORD*)linetab + 1);
-    lbh = (const struct codeview_linetab2_block*)(linetab + 8 + offset);
-    while ((const char*)lbh < linetab + size)
+    const struct codeview_linetab2*     lt2;
+    const struct codeview_linetab2*     lt2_files = NULL;
+    const struct codeview_lt2blk_lines* lines_blk;
+    const struct codeview_linetab2_file*fd;
+
+    /* locate LT2_FILES_BLOCK (if any) */
+    lt2 = (const struct codeview_linetab2*)linetab;
+    while ((const char*)(lt2 + 1) < linetab + size)
     {
-        if (lbh->header != 0x000000f2)
-        /* FIXME: should also check that whole lbh fits in linetab + size */
+        if (lt2->header == LT2_FILES_BLOCK)
         {
-            /* printf("%sblock end %x\n", pfx, lbh->header); */
+            lt2_files = lt2;
             break;
         }
-        printf("%sblock from %04x:%08x #%x (%x lines)\n",
-               pfx, lbh->seg, lbh->start, lbh->size, lbh->nlines);
-        fd = (const struct codeview_linetab2_file*)(linetab + 8 + lbh->file_offset);
-        printf("%s  md5=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
-               pfx, fd->md5[ 0], fd->md5[ 1], fd->md5[ 2], fd->md5[ 3],
-               fd->md5[ 4], fd->md5[ 5], fd->md5[ 6], fd->md5[ 7],
-               fd->md5[ 8], fd->md5[ 9], fd->md5[10], fd->md5[11],
-               fd->md5[12], fd->md5[13], fd->md5[14], fd->md5[15]);
-        /* FIXME: should check that string is within strimage + strsize */
-        printf("%s  file=%s\n", pfx, strimage ? strimage + fd->offset : "--none--");
-        for (i = 0; i < lbh->nlines; i++)
+        lt2 = codeview_linetab2_next_block(lt2);
+    }
+    if (!lt2_files)
+    {
+        printf("%sNo LT2_FILES_BLOCK found\n", pfx);
+        return;
+    }
+
+    lt2 = (const struct codeview_linetab2*)linetab;
+    while ((const char*)(lt2 + 1) < linetab + size)
+    {
+        /* FIXME: should also check that whole lbh fits in linetab + size */
+        switch (lt2->header)
         {
-            printf("%s  offset=%08x line=%d\n", pfx, lbh->l[i].offset, lbh->l[i].lineno ^ 0x80000000);
+        case LT2_LINES_BLOCK:
+            lines_blk = (const struct codeview_lt2blk_lines*)lt2;
+            printf("%sblock from %04x:%08x #%x (%x lines) fo=%x\n",
+                   pfx, lines_blk->seg, lines_blk->start, lines_blk->size,
+                   lines_blk->nlines, lines_blk->file_offset);
+            /* FIXME: should check that file_offset is within the LT2_FILES_BLOCK we've seen */
+            fd = (const struct codeview_linetab2_file*)((const char*)lt2_files + 8 + lines_blk->file_offset);
+            printf("%s  md5=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+                   pfx, fd->md5[ 0], fd->md5[ 1], fd->md5[ 2], fd->md5[ 3],
+                   fd->md5[ 4], fd->md5[ 5], fd->md5[ 6], fd->md5[ 7],
+                   fd->md5[ 8], fd->md5[ 9], fd->md5[10], fd->md5[11],
+                   fd->md5[12], fd->md5[13], fd->md5[14], fd->md5[15]);
+            /* FIXME: should check that string is within strimage + strsize */
+            printf("%s  file=%s\n", pfx, strimage ? strimage + fd->offset : "--none--");
+            for (i = 0; i < lines_blk->nlines; i++)
+            {
+                printf("%s  offset=%08x line=%d\n",
+                       pfx, lines_blk->l[i].offset, lines_blk->l[i].lineno ^ 0x80000000);
+            }
+            break;
+        case LT2_FILES_BLOCK: /* skip */
+            break;
+        default:
+            printf("%sblock end %x\n", pfx, lt2->header);
+            lt2 = (const struct codeview_linetab2*)((const char*)linetab + size);
+            continue;
         }
-        lbh = (const struct codeview_linetab2_block*)((const char*)lbh + 8 + lbh->size_of_block);
+        lt2 = codeview_linetab2_next_block(lt2);
     }
 }






More information about the wine-patches mailing list