- implemented EnumDirTree, SearchTreeForFile, SymFindFileInPath,
SymMatchFileName - made use of SymFindFileInPath to lookup .dbg and .pdb files - fixed a crash in CodeView enum handling
This commit is contained in:
parent
bc06d4ba8e
commit
eb25084eee
|
@ -1,5 +1,6 @@
|
||||||
@ stub DbgHelpCreateUserDump
|
@ stub DbgHelpCreateUserDump
|
||||||
@ stub DbgHelpCreateUserDumpW
|
@ stub DbgHelpCreateUserDumpW
|
||||||
|
@ stdcall EnumDirTree(long str str ptr ptr ptr)
|
||||||
@ stdcall EnumerateLoadedModules(long ptr ptr)
|
@ stdcall EnumerateLoadedModules(long ptr ptr)
|
||||||
@ stub EnumerateLoadedModules64
|
@ stub EnumerateLoadedModules64
|
||||||
@ stub ExtensionApiVersion
|
@ stub ExtensionApiVersion
|
||||||
|
@ -35,7 +36,7 @@
|
||||||
@ stub SymEnumerateSymbols64
|
@ stub SymEnumerateSymbols64
|
||||||
@ stub SymEnumerateSymbolsW
|
@ stub SymEnumerateSymbolsW
|
||||||
@ stub SymEnumerateSymbolsW64
|
@ stub SymEnumerateSymbolsW64
|
||||||
@ stub SymFindFileInPath
|
@ stdcall SymFindFileInPath(long str str ptr long long long ptr ptr ptr)
|
||||||
@ stdcall SymFromAddr(long long ptr ptr)
|
@ stdcall SymFromAddr(long long ptr ptr)
|
||||||
@ stdcall SymFromName(long str ptr)
|
@ stdcall SymFromName(long str ptr)
|
||||||
@ stdcall SymFunctionTableAccess(long long)
|
@ stdcall SymFunctionTableAccess(long long)
|
||||||
|
@ -71,7 +72,7 @@
|
||||||
@ stdcall SymLoadModule(long long str str long long)
|
@ stdcall SymLoadModule(long long str str long long)
|
||||||
@ stub SymLoadModule64
|
@ stub SymLoadModule64
|
||||||
@ stub SymLoadModuleEx
|
@ stub SymLoadModuleEx
|
||||||
@ stub SymMatchFileName
|
@ stdcall SymMatchFileName(str str ptr ptr)
|
||||||
@ stub SymMatchString
|
@ stub SymMatchString
|
||||||
@ stdcall SymRegisterCallback(long ptr ptr)
|
@ stdcall SymRegisterCallback(long ptr ptr)
|
||||||
@ stub SymRegisterCallback64
|
@ stub SymRegisterCallback64
|
||||||
|
|
|
@ -2676,12 +2676,10 @@ static void pdb_convert_symbols_header(PDB_SYMBOLS* symbols,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* get_last_sep(const char* str)
|
static BOOL CALLBACK pdb_match(char* file, void* user)
|
||||||
{
|
{
|
||||||
char* a;
|
/* accept first file */
|
||||||
|
return FALSE;
|
||||||
if ((a = strrchr(str, '/'))) str = a;
|
|
||||||
return (a = strrchr(str, '\\')) ? a : str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HANDLE open_pdb_file(const struct process* pcs, struct module* module,
|
static HANDLE open_pdb_file(const struct process* pcs, struct module* module,
|
||||||
|
@ -2692,24 +2690,14 @@ static HANDLE open_pdb_file(const struct process* pcs, struct module* module,
|
||||||
|
|
||||||
h = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
h = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
/* 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 = FindDebugInfoFile((char*)filename, pcs->search_path, dbg_file_path);
|
|
||||||
if (h == NULL)
|
|
||||||
{
|
|
||||||
const char* p;
|
|
||||||
const char* q;
|
|
||||||
|
|
||||||
strcpy(dbg_file_path, module->module.LoadedImageName);
|
|
||||||
if ((p = get_last_sep(dbg_file_path)))
|
|
||||||
{
|
|
||||||
if ((q = get_last_sep(filename))) q++; else q = filename;
|
|
||||||
strcpy((char*)p + 1, q);
|
|
||||||
h = CreateFileA(dbg_file_path, GENERIC_READ, FILE_SHARE_READ, NULL,
|
h = CreateFileA(dbg_file_path, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return (h == INVALID_HANDLE_VALUE) ? NULL : h;
|
return (h == INVALID_HANDLE_VALUE) ? NULL : h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,16 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||||
|
|
||||||
|
static inline BOOL is_sep(char ch) {return ch == '/' || ch == '\\';}
|
||||||
|
|
||||||
|
static inline char* file_name(char* str)
|
||||||
|
{
|
||||||
|
char* p;
|
||||||
|
|
||||||
|
for (p = str + strlen(str) - 1; p >= str && !is_sep(*p); p--);
|
||||||
|
return p + 1;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* FindDebugInfoFile (DBGHELP.@)
|
* FindDebugInfoFile (DBGHELP.@)
|
||||||
*
|
*
|
||||||
|
@ -40,9 +50,7 @@ HANDLE WINAPI FindDebugInfoFile(PSTR FileName, PSTR SymbolPath, PSTR DebugFilePa
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
const char* p = strrchr(FileName, '/');
|
if (!SearchPathA(SymbolPath, file_name(FileName), NULL, MAX_PATH, DebugFilePath, NULL))
|
||||||
if (!p) p = FileName;
|
|
||||||
if (!SearchPathA(SymbolPath, p, NULL, MAX_PATH, DebugFilePath, NULL))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
|
h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
@ -92,15 +100,160 @@ BOOL WINAPI MakeSureDirectoryPathExists(LPCSTR DirPath)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* SymMatchFileName (DBGHELP.@)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SymMatchFileName(char* file, char* match,
|
||||||
|
char** filestop, char** matchstop)
|
||||||
|
{
|
||||||
|
char* fptr;
|
||||||
|
char* mptr;
|
||||||
|
|
||||||
|
TRACE("(%s %s %p %p)\n", file, match, filestop, matchstop);
|
||||||
|
|
||||||
|
fptr = file + strlen(file) - 1;
|
||||||
|
mptr = match + strlen(match) - 1;
|
||||||
|
|
||||||
|
while (fptr >= file && mptr >= match)
|
||||||
|
{
|
||||||
|
if (toupper(*fptr) != toupper(*mptr) && !(is_sep(*fptr) && is_sep(*mptr)))
|
||||||
|
break;
|
||||||
|
fptr--; mptr--;
|
||||||
|
}
|
||||||
|
if (filestop) *filestop = fptr;
|
||||||
|
if (matchstop) *matchstop = mptr;
|
||||||
|
|
||||||
|
return mptr == match - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL do_search(const char* file, char* buffer,
|
||||||
|
PENUMDIRTREE_CALLBACK cb, void* user)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
WIN32_FIND_DATAA fd;
|
||||||
|
unsigned pos;
|
||||||
|
BOOL found = FALSE;
|
||||||
|
|
||||||
|
pos = strlen(buffer);
|
||||||
|
if (buffer[pos - 1] != '\\') buffer[pos++] = '\\';
|
||||||
|
strcpy(buffer + pos, "*.*");
|
||||||
|
if ((h = FindFirstFileA(buffer, &fd)) == INVALID_HANDLE_VALUE)
|
||||||
|
return FALSE;
|
||||||
|
/* doc doesn't specify how the tree is enumerated...
|
||||||
|
* doing a depth first based on, but may be wrong
|
||||||
|
*/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")) continue;
|
||||||
|
|
||||||
|
strcpy(buffer + pos, fd.cFileName);
|
||||||
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
found = do_search(file, buffer, cb, user);
|
||||||
|
else if (SymMatchFileName(buffer, (char*)file, NULL, NULL))
|
||||||
|
{
|
||||||
|
if (!cb || cb(buffer, user)) found = TRUE;
|
||||||
|
}
|
||||||
|
} while (!found && FindNextFileA(h, &fd));
|
||||||
|
if (!found) buffer[--pos] = '\0';
|
||||||
|
FindClose(h);
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* SearchTreeForFile (DBGHELP.@)
|
* SearchTreeForFile (DBGHELP.@)
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI SearchTreeForFile(LPSTR RootPath, LPSTR InputPathName,
|
BOOL WINAPI SearchTreeForFile(LPSTR root, LPSTR file, LPSTR buffer)
|
||||||
LPSTR OutputPathBuffer)
|
|
||||||
{
|
{
|
||||||
FIXME("(%s, %s, %s): stub\n",
|
TRACE("(%s, %s, %p)\n",
|
||||||
debugstr_a(RootPath), debugstr_a(InputPathName),
|
debugstr_a(root), debugstr_a(file), buffer);
|
||||||
debugstr_a(OutputPathBuffer));
|
strcpy(buffer, root);
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
return do_search(file, buffer, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* EnumDirTree (DBGHELP.@)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WINAPI EnumDirTree(HANDLE hProcess, PCSTR root, PCSTR file,
|
||||||
|
LPSTR buffer, PENUMDIRTREE_CALLBACK cb, void* user)
|
||||||
|
{
|
||||||
|
TRACE("(%p %s %s %p %p %p)\n", hProcess, root, file, buffer, cb, user);
|
||||||
|
|
||||||
|
strcpy(buffer, root);
|
||||||
|
return do_search(file, buffer, cb, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sffip
|
||||||
|
{
|
||||||
|
PVOID id;
|
||||||
|
DWORD two;
|
||||||
|
DWORD three;
|
||||||
|
DWORD flags;
|
||||||
|
PFINDFILEINPATHCALLBACK cb;
|
||||||
|
void* user;
|
||||||
|
};
|
||||||
|
|
||||||
|
static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* user)
|
||||||
|
{
|
||||||
|
struct sffip* s = (struct sffip*)user;
|
||||||
|
|
||||||
|
/* FIXME: should check that id/two/three match the file pointed
|
||||||
|
* by buffer
|
||||||
|
*/
|
||||||
|
/* yes, EnumDirTree and SymFindFileInPath callbacks use the opposite
|
||||||
|
* convention to stop/continue enumeration. sigh.
|
||||||
|
*/
|
||||||
|
return !(s->cb)((char*)buffer, s->user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* SymFindFileInPath (DBGHELP.@)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR file,
|
||||||
|
PVOID id, DWORD two, DWORD three, DWORD flags,
|
||||||
|
LPSTR buffer, PFINDFILEINPATHCALLBACK cb,
|
||||||
|
PVOID user)
|
||||||
|
{
|
||||||
|
struct sffip s;
|
||||||
|
struct process* pcs = process_find_by_handle(hProcess);
|
||||||
|
char tmp[MAX_PATH];
|
||||||
|
char* ptr;
|
||||||
|
|
||||||
|
TRACE("(%p %s %s %p %08lx %08lx %08lx %p %p %p)\n",
|
||||||
|
hProcess, searchPath, file, id, two, three, flags,
|
||||||
|
buffer, cb, user);
|
||||||
|
|
||||||
|
if (!pcs) return FALSE;
|
||||||
|
if (!searchPath) searchPath = pcs->search_path;
|
||||||
|
|
||||||
|
s.id = id;
|
||||||
|
s.two = two;
|
||||||
|
s.three = three;
|
||||||
|
s.flags = flags;
|
||||||
|
s.cb = cb;
|
||||||
|
s.user = user;
|
||||||
|
|
||||||
|
file = file_name(file);
|
||||||
|
|
||||||
|
while (searchPath)
|
||||||
|
{
|
||||||
|
ptr = strchr(searchPath, ';');
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
memcpy(tmp, searchPath, ptr - searchPath);
|
||||||
|
tmp[ptr - searchPath] = 0;
|
||||||
|
searchPath = ptr + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(tmp, searchPath);
|
||||||
|
searchPath = NULL;
|
||||||
|
}
|
||||||
|
if (EnumDirTree(hProcess, tmp, file, buffer, sffip_cb, &s)) return TRUE;
|
||||||
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,12 @@ static SYM_TYPE pe_load_stabs(const struct process* pcs, struct module* module,
|
||||||
return sym_type;
|
return sym_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL CALLBACK dbg_match(char* file, void* user)
|
||||||
|
{
|
||||||
|
/* accept first file */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* pe_load_dbg_file
|
* pe_load_dbg_file
|
||||||
*
|
*
|
||||||
|
@ -81,7 +87,7 @@ static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* modul
|
||||||
const char* dbg_name, DWORD timestamp)
|
const char* dbg_name, DWORD timestamp)
|
||||||
{
|
{
|
||||||
char tmp[MAX_PATH];
|
char tmp[MAX_PATH];
|
||||||
HANDLE hFile, hMap = 0;
|
HANDLE hFile = INVALID_HANDLE_VALUE, hMap = 0;
|
||||||
const BYTE* dbg_mapping = NULL;
|
const BYTE* dbg_mapping = NULL;
|
||||||
const IMAGE_SEPARATE_DEBUG_HEADER* hdr;
|
const IMAGE_SEPARATE_DEBUG_HEADER* hdr;
|
||||||
const IMAGE_DEBUG_DIRECTORY* dbg;
|
const IMAGE_DEBUG_DIRECTORY* dbg;
|
||||||
|
@ -89,8 +95,11 @@ static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* modul
|
||||||
|
|
||||||
WINE_TRACE("Processing DBG file %s\n", dbg_name);
|
WINE_TRACE("Processing DBG file %s\n", dbg_name);
|
||||||
|
|
||||||
tmp[0] = '\0';
|
if (SymFindFileInPath(pcs->handle, NULL, (char*)dbg_name,
|
||||||
if ((hFile = FindDebugInfoFile((char*)dbg_name, pcs->search_path, tmp)) != NULL &&
|
NULL, 0, 0, 0,
|
||||||
|
tmp, dbg_match, NULL) &&
|
||||||
|
(hFile = CreateFileA(tmp, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE &&
|
||||||
((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
|
((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
|
||||||
((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL))
|
((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL))
|
||||||
{
|
{
|
||||||
|
|
|
@ -238,7 +238,7 @@ struct symt_enum* symt_new_enum(struct module* module, const char* typename)
|
||||||
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
|
if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
|
||||||
{
|
{
|
||||||
sym->symt.tag = SymTagEnum;
|
sym->symt.tag = SymTagEnum;
|
||||||
sym->name = pool_strdup(&module->pool, typename);
|
sym->name = (typename) ? pool_strdup(&module->pool, typename) : NULL;
|
||||||
vector_init(&sym->vchildren, sizeof(struct symt*), 8);
|
vector_init(&sym->vchildren, sizeof(struct symt*), 8);
|
||||||
}
|
}
|
||||||
return sym;
|
return sym;
|
||||||
|
|
|
@ -749,6 +749,10 @@ BOOL WINAPI SymSetSearchPath(HANDLE,PSTR);
|
||||||
DWORD WINAPI GetTimestampForLoadedLibrary(HMODULE);
|
DWORD WINAPI GetTimestampForLoadedLibrary(HMODULE);
|
||||||
BOOL WINAPI MakeSureDirectoryPathExists(PCSTR);
|
BOOL WINAPI MakeSureDirectoryPathExists(PCSTR);
|
||||||
BOOL WINAPI SearchTreeForFile(PSTR,PSTR,PSTR);
|
BOOL WINAPI SearchTreeForFile(PSTR,PSTR,PSTR);
|
||||||
|
typedef BOOL (CALLBACK *PENUMDIRTREE_CALLBACK)(LPCSTR path, PVOID user);
|
||||||
|
BOOL WINAPI EnumDirTree(HANDLE hProcess, PCSTR root, PCSTR file,
|
||||||
|
LPSTR buffer, PENUMDIRTREE_CALLBACK cb, void* user);
|
||||||
|
BOOL WINAPI SymMatchFileName(LPSTR file, LPSTR match, LPSTR* filestop, LPSTR* matchstop);
|
||||||
|
|
||||||
/*************************
|
/*************************
|
||||||
* Context management *
|
* Context management *
|
||||||
|
|
Loading…
Reference in New Issue