[PATCH 14/14] [DbgHelp]: SymFindFileInPath and PDB

Eric Pouech eric.pouech at wanadoo.fr
Wed May 10 14:35:51 CDT 2006


- implemented correct lookup when SymFindFileInPath is
  called to find a PDB file
- added pdb_fetch_file_info to gather relevant information
- when looking for a PDB file (from a .EXE or a .DLL), now
  using SymFindFileInPath to locate the PDB file with the
  correct information

A+
---

 dlls/dbghelp/dbghelp_private.h |   24 ++++
 dlls/dbghelp/msc.c             |  240 +++++++++++++++++++++++-----------------
 dlls/dbghelp/mscvpdb.h         |    6 +
 dlls/dbghelp/path.c            |   46 +++++++-
 4 files changed, 207 insertions(+), 109 deletions(-)

diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h
index 1abb2cc..564537b 100644
--- a/dlls/dbghelp/dbghelp_private.h
+++ b/dlls/dbghelp/dbghelp_private.h
@@ -325,6 +325,28 @@ struct module_pair
     struct module*              effective; /* out: module with debug info */
 };
 
+enum pdb_kind {PDB_JG, PDB_DS};
+
+struct pdb_lookup
+{
+    const char*                 filename;
+    DWORD                       age;
+    enum pdb_kind               kind;
+    union
+    {
+        struct
+        {
+            DWORD               timestamp;
+            struct PDB_JG_TOC*  toc;
+        } jg;
+        struct
+        {
+            GUID                guid;
+            struct PDB_DS_TOC*  toc;
+        } ds;
+    } u;
+};
+
 /* dbghelp.c */
 extern struct process* process_find_by_handle(HANDLE hProcess);
 extern HANDLE hMsvcrt;
@@ -376,6 +398,8 @@ extern BOOL         pe_load_debug_direct
                                             const BYTE* mapping,
                                             const IMAGE_SECTION_HEADER* sectp, DWORD nsect,
                                             const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg);
+extern BOOL         pdb_fetch_file_info(struct pdb_lookup* pdb_lookup);
+
 /* pe_module.c */
 extern BOOL         pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth);
 extern struct module*
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c
index 32c5f3a..9849a91 100644
--- a/dlls/dbghelp/msc.c
+++ b/dlls/dbghelp/msc.c
@@ -1636,25 +1636,6 @@ static int codeview_snarf(const struct m
  * Process PDB file.
  */
 
-struct pdb_lookup
-{
-    const char*                 filename;
-    enum {PDB_JG, PDB_DS}       kind;
-    union
-    {
-        struct
-        {
-            DWORD               timestamp;
-            struct PDB_JG_TOC*  toc;
-        } jg;
-        struct
-        {
-            GUID                guid;
-            struct PDB_DS_TOC*  toc;
-        } ds;
-    } u;
-};
-
 static void* pdb_jg_read(const struct PDB_JG_HEADER* pdb, const WORD* block_list,
                          int size)
 {
@@ -1856,22 +1837,35 @@ static BOOL CALLBACK pdb_match(char* fil
     return TRUE;
 }
 
-static HANDLE open_pdb_file(const struct process* pcs, const char* filename)
+static HANDLE open_pdb_file(const struct process* pcs,
+                            const struct pdb_lookup* lookup)
 {
     HANDLE      h;
     char        dbg_file_path[MAX_PATH];
+    BOOL        ret = FALSE;
 
-    h = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
-                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-    /* FIXME: should give more bits on the file to look at */
-    if (h == INVALID_HANDLE_VALUE &&
-        SymFindFileInPath(pcs->handle, NULL, (char*)filename, NULL, 0, 0, 0,
-                          dbg_file_path, pdb_match, NULL))
-    {
-        h = CreateFileA(dbg_file_path, GENERIC_READ, FILE_SHARE_READ, NULL, 
-                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-        TRACE("with %s returns %p\n", dbg_file_path, h);
+    switch (lookup->kind)
+    {
+    case PDB_JG:
+        ret = SymFindFileInPath(pcs->handle, NULL, lookup->filename, 
+                                (PVOID)(DWORD_PTR)lookup->u.jg.timestamp,
+                                lookup->age, 0, SSRVOPT_DWORD,
+                                dbg_file_path, pdb_match, NULL);
+        break;
+    case PDB_DS:
+        ret = SymFindFileInPath(pcs->handle, NULL, lookup->filename, 
+                                (PVOID)&lookup->u.ds.guid, lookup->age, 0, 
+                                SSRVOPT_GUIDPTR, dbg_file_path, pdb_match, NULL);
+        break;
+    }
+    if (!ret)
+    {
+        WARN("\tCouldn't find %s\n", lookup->filename);
+        return NULL;
     }
+    h = CreateFileA(dbg_file_path, GENERIC_READ, FILE_SHARE_READ, NULL, 
+                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    TRACE("%s: %s returns %p\n", lookup->filename, dbg_file_path, h);
     return (h == INVALID_HANDLE_VALUE) ? NULL : h;
 }
 
@@ -1928,91 +1922,95 @@ static void pdb_process_types(const stru
 static const char       PDB_JG_IDENT[] = "Microsoft C/C++ program database 2.00\r\n\032JG\0";
 static const char       PDB_DS_IDENT[] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0";
 
-static BOOL pdb_init(struct pdb_lookup* pdb_lookup, const char* image)
+/******************************************************************
+ *		pdb_init
+ *
+ * Tries to load a pdb file
+ * if do_fill is TRUE, then it just fills pdb_lookup with the information of the
+ *      file
+ * if do_fill is FALSE, then it just checks that the kind of PDB (stored in
+ *      pdb_lookup) matches what's really in the file
+ */
+static BOOL pdb_init(struct pdb_lookup* pdb_lookup, const char* image, BOOL do_fill)
 {
+    BOOL        ret = TRUE;
+
     /* check the file header, and if ok, load the TOC */
     TRACE("PDB(%s): %.40s\n", pdb_lookup->filename, debugstr_an(image, 40));
-    switch (pdb_lookup->kind)
+
+    if (!memcmp(image, PDB_JG_IDENT, sizeof(PDB_JG_IDENT)))
     {
-    case PDB_JG:
-        pdb_lookup->u.jg.toc = NULL;
-        if (memcmp(image, PDB_JG_IDENT, sizeof(PDB_JG_IDENT)))
+        const struct PDB_JG_HEADER* pdb = (const struct PDB_JG_HEADER*)image;
+        struct PDB_JG_ROOT*         root;
+
+        pdb_lookup->u.jg.toc = pdb_jg_read(pdb, pdb->toc_block, pdb->toc.size);
+        root = pdb_read_jg_file(pdb, pdb_lookup->u.jg.toc, 1);
+        if (!root)
         {
-            FIXME("Couldn't match JG header\n");
+            ERR("-Unable to get root from .PDB in %s\n", pdb_lookup->filename);
             return FALSE;
         }
-        else
+        switch (root->Version)
         {
-            const struct PDB_JG_HEADER* pdb = (const struct PDB_JG_HEADER*)image;
-            struct PDB_JG_ROOT*         root;
-
-            pdb_lookup->u.jg.toc = pdb_jg_read(pdb, pdb->toc_block, pdb->toc.size);
-            root = pdb_read_jg_file(pdb, pdb_lookup->u.jg.toc, 1);
-            if (!root)
-            {
-                ERR("-Unable to get root from .PDB in %s\n", pdb_lookup->filename);
-                return FALSE;
-            }
-            switch (root->Version)
-            {
-            case 19950623:      /* VC 4.0 */
-            case 19950814:
-            case 19960307:      /* VC 5.0 */
-            case 19970604:      /* VC 6.0 */
-                break;
-            default:
-                ERR("-Unknown root block version %ld\n", root->Version);
-            } 
-            /* Check .PDB time stamp */
-            if (root->TimeDateStamp != pdb_lookup->u.jg.timestamp)
-            {
-                ERR("-Wrong time stamp of .PDB file %s (0x%08lx, 0x%08lx)\n",
-                    pdb_lookup->filename, root->TimeDateStamp, 
-                    pdb_lookup->u.jg.timestamp);
-            }
-            pdb_free(root);
+        case 19950623:      /* VC 4.0 */
+        case 19950814:
+        case 19960307:      /* VC 5.0 */
+        case 19970604:      /* VC 6.0 */
+            break;
+        default:
+            ERR("-Unknown root block version %ld\n", root->Version);
         }
-        break;
-    case PDB_DS:
-        pdb_lookup->u.ds.toc = NULL;
-        if (memcmp(image, PDB_DS_IDENT, sizeof(PDB_DS_IDENT)))
+        if (do_fill)
         {
-            FIXME("Couldn't match DS header\n");
+            pdb_lookup->kind = PDB_JG;
+            pdb_lookup->u.jg.timestamp = root->TimeDateStamp;
+            pdb_lookup->age = root->Age;
+        }
+        else if (pdb_lookup->kind != PDB_JG ||
+                 pdb_lookup->u.jg.timestamp != root->TimeDateStamp ||
+                 pdb_lookup->age != root->Age)
+            ret = FALSE;
+        TRACE("found JG/%c for %s: age=%lx timestamp=%lx\n",
+              do_fill ? 'f' : '-', pdb_lookup->filename, root->Age,
+              root->TimeDateStamp);
+        pdb_free(root);
+    }
+    else if (!memcmp(image, PDB_DS_IDENT, sizeof(PDB_DS_IDENT)))
+    {
+        const struct PDB_DS_HEADER* pdb = (const struct PDB_DS_HEADER*)image;
+        struct PDB_DS_ROOT*         root;
+
+        pdb_lookup->u.ds.toc = 
+            pdb_ds_read(pdb, 
+                        (const DWORD*)((const char*)pdb + pdb->toc_page * pdb->block_size), 
+                        pdb->toc_size);
+        root = pdb_read_ds_file(pdb, pdb_lookup->u.ds.toc, 1);
+        if (!root)
+        {
+            ERR("-Unable to get root from .PDB in %s\n", pdb_lookup->filename);
             return FALSE;
         }
-        else
+        switch (root->Version)
         {
-            const struct PDB_DS_HEADER* pdb = (const struct PDB_DS_HEADER*)image;
-            struct PDB_DS_ROOT*         root;
-
-            pdb_lookup->u.ds.toc = 
-                pdb_ds_read(pdb, 
-                            (const DWORD*)((const char*)pdb + pdb->toc_page * pdb->block_size), 
-                            pdb->toc_size);
-            root = pdb_read_ds_file(pdb, pdb_lookup->u.ds.toc, 1);
-            if (!root)
-            {
-                ERR("-Unable to get root from .PDB in %s\n", pdb_lookup->filename);
-                return FALSE;
-            }
-            switch (root->Version)
-            {
-            case 20000404:
-                break;
-            default:
-                ERR("-Unknown root block version %ld\n", root->Version);
-            } 
-            /* Check .PDB time stamp */
-            if (memcmp(&root->guid, &pdb_lookup->u.ds.guid, sizeof(GUID)))
-            {
-                ERR("-Wrong GUID of .PDB file %s (%s, %s)\n",
-                    pdb_lookup->filename, 
-                    wine_dbgstr_guid(&root->guid), 
-                    wine_dbgstr_guid(&pdb_lookup->u.ds.guid));
-            }
-            pdb_free(root);
+        case 20000404:
+            break;
+        default:
+            ERR("-Unknown root block version %ld\n", root->Version);
         }
-        break;
+        if (do_fill)
+        {
+            pdb_lookup->kind = PDB_DS;
+            pdb_lookup->u.ds.guid = root->guid;
+            pdb_lookup->age = root->Age;
+        }
+        else if (pdb_lookup->kind != PDB_DS ||
+                 memcmp(&pdb_lookup->u.ds.guid, &root->guid, sizeof(GUID)) ||
+                 pdb_lookup->age != root->Age)
+            ret = FALSE;
+        TRACE("found DS/%c for %s: age=%lx guid=%s\n",
+              do_fill ? 'f' : '-', pdb_lookup->filename, root->Age,
+              debugstr_guid(&root->guid));
+        pdb_free(root);
     }
 
     if (0) /* some tool to dump the internal files from a PDB file */
@@ -2034,7 +2032,7 @@ static BOOL pdb_init(struct pdb_lookup* 
             pdb_free(x);
         }
     }
-    return TRUE;
+    return ret;
 }
 
 static BOOL pdb_process_internal(const struct process* pcs, 
@@ -2075,9 +2073,15 @@ static void pdb_process_symbol_imports(c
             {
                 struct pdb_lookup       imp_pdb_lookup;
 
+                /* FIXME: this is an import of a JG PDB file
+                 * how's a DS PDB handled ?
+                 */
                 imp_pdb_lookup.filename = imp->filename;
                 imp_pdb_lookup.kind = PDB_JG;
                 imp_pdb_lookup.u.jg.timestamp = imp->TimeDateStamp;
+                imp_pdb_lookup.age = imp->Age;
+                TRACE("got for %s: age=%lu ts=%lx\n",
+                      imp->filename, imp->Age, imp->TimeDateStamp);
                 pdb_process_internal(pcs, msc_dbg, &imp_pdb_lookup, i);
             }
             i++;
@@ -2103,14 +2107,14 @@ static BOOL pdb_process_internal(const s
     TRACE("Processing PDB file %s\n", pdb_lookup->filename);
 
     /* Open and map() .PDB file */
-    if ((hFile = open_pdb_file(pcs, pdb_lookup->filename)) == NULL ||
+    if ((hFile = open_pdb_file(pcs, pdb_lookup)) == NULL ||
         ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) == NULL) ||
         ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL))
     {
         WARN("Unable to open .PDB file: %s\n", pdb_lookup->filename);
         goto leave;
     }
-    pdb_init(pdb_lookup, image);
+    pdb_init(pdb_lookup, image, FALSE);
 
     symbols_image = pdb_read_file(image, pdb_lookup, 3);
     if (symbols_image)
@@ -2209,6 +2213,33 @@ static BOOL pdb_process_file(const struc
     return ret;
 }
 
+BOOL pdb_fetch_file_info(struct pdb_lookup* pdb_lookup)
+{
+    HANDLE              hFile, hMap = NULL;
+    char*               image = NULL;
+    BOOL                ret = TRUE;
+
+    if ((hFile = CreateFileA(pdb_lookup->filename, GENERIC_READ, FILE_SHARE_READ, NULL, 
+                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE ||
+        ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) == NULL) ||
+        ((image = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) == NULL))
+    {
+        WARN("Unable to open .PDB file: %s\n", pdb_lookup->filename);
+        ret = FALSE;
+    }
+    else
+    {
+        pdb_init(pdb_lookup, image, TRUE);
+        pdb_free_lookup(pdb_lookup);
+    }
+
+    if (image) UnmapViewOfFile(image);
+    if (hMap) CloseHandle(hMap);
+    if (hFile) CloseHandle(hFile);
+
+    return ret;
+}
+
 /*========================================================================
  * Process CodeView debug information.
  */
@@ -2313,6 +2344,7 @@ static BOOL codeview_process_info(const 
         pdb_lookup.kind = PDB_JG;
         pdb_lookup.u.jg.timestamp = pdb->timestamp;
         pdb_lookup.u.jg.toc = NULL;
+        pdb_lookup.age = pdb->unknown;
         ret = pdb_process_file(pcs, msc_dbg, &pdb_lookup);
         break;
     }
diff --git a/dlls/dbghelp/mscvpdb.h b/dlls/dbghelp/mscvpdb.h
index a63918a..cb97ac2 100644
--- a/dlls/dbghelp/mscvpdb.h
+++ b/dlls/dbghelp/mscvpdb.h
@@ -1300,7 +1300,7 @@ struct PDB_JG_ROOT
 {
     DWORD               Version;
     DWORD               TimeDateStamp;
-    DWORD               unknown;
+    DWORD               Age;
     DWORD               cbNames;
     CHAR                names[1];
 };
@@ -1309,7 +1309,7 @@ struct PDB_DS_ROOT
 {
     DWORD               Version;
     DWORD               TimeDateStamp;
-    DWORD               unknown;
+    DWORD               Age;
     GUID                guid;
     DWORD               cbNames;
     CHAR                names[1];
@@ -1409,7 +1409,7 @@ typedef struct _PDB_SYMBOL_IMPORT
     DWORD       unknown1;
     DWORD       unknown2;
     DWORD       TimeDateStamp;
-    DWORD       nRequests;
+    DWORD       Age;
     CHAR        filename[1];
 } PDB_SYMBOL_IMPORT, *PPDB_SYMBOL_IMPORT;
 
diff --git a/dlls/dbghelp/path.c b/dlls/dbghelp/path.c
index fbd3b6e..374bfb6 100644
--- a/dlls/dbghelp/path.c
+++ b/dlls/dbghelp/path.c
@@ -229,7 +229,6 @@ static BOOL CALLBACK sffip_cb(LPCSTR buf
 {
     struct sffip*       s = (struct sffip*)user;
     DWORD               size, checksum;
-    DWORD_PTR           timestamp;
 
     /* FIXME: should check that id/two/three match the file pointed
      * by buffer
@@ -240,6 +239,7 @@ static BOOL CALLBACK sffip_cb(LPCSTR buf
         {
             HANDLE  hFile, hMap;
             void*   mapping;
+            DWORD   timestamp;
 
             timestamp = ~(DWORD_PTR)s->id;
             size = ~s->two;
@@ -282,7 +282,49 @@ static BOOL CALLBACK sffip_cb(LPCSTR buf
         }
         break;
     case DMT_PDB:
-        FIXME("NIY on '%s'\n", buffer);
+        {
+            struct pdb_lookup   pdb_lookup;
+
+            pdb_lookup.filename = buffer;
+
+            if (!pdb_fetch_file_info(&pdb_lookup)) return FALSE;
+            switch (pdb_lookup.kind)
+            {
+            case PDB_JG:
+                if (s->flags & SSRVOPT_GUIDPTR)
+                {
+                    WARN("Found %s, but wrong PDB version\n", buffer);
+                    return FALSE;
+                }
+                if (pdb_lookup.u.jg.timestamp != (DWORD_PTR)s->id)
+                {
+                    WARN("Found %s, but wrong signature: %08lx %08lx\n",
+                         buffer, pdb_lookup.u.jg.timestamp, (DWORD_PTR)s->id);
+                    return FALSE;
+                }
+                break;
+            case PDB_DS:
+                if (!(s->flags & SSRVOPT_GUIDPTR))
+                {
+                    WARN("Found %s, but wrong PDB version\n", buffer);
+                    return FALSE;
+                }
+                if (!(memcmp(&pdb_lookup.u.ds.guid, (GUID*)s->id, sizeof(GUID))))
+                {
+                    WARN("Found %s, but wrong GUID: %s %s\n",
+                         buffer, debugstr_guid(&pdb_lookup.u.ds.guid),
+                         debugstr_guid((GUID*)s->id));
+                    return FALSE;
+                }
+                break;
+            }
+            if (pdb_lookup.age != s->two)
+            {
+                WARN("Found %s, but wrong age: %08lx %08lx\n",
+                     buffer, pdb_lookup.age, s->two);
+                return FALSE;
+            }
+        }
         break;
     default:
         FIXME("What the heck??\n");




More information about the wine-patches mailing list