[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