- Various improvements for minidump module information
. added timestamp & checksum in PE module . added size & checksum in ELF module . wine loader now appears with its pathname. - Implemented PE & ELF timestamp & checksum validation in SymFindFileInPath.
This commit is contained in:
parent
d54db1911e
commit
7ea69cc7ea
|
@ -249,6 +249,7 @@ enum module_type
|
||||||
DMT_UNKNOWN, /* for lookup, not actually used for a module */
|
DMT_UNKNOWN, /* for lookup, not actually used for a module */
|
||||||
DMT_ELF, /* a real ELF shared module */
|
DMT_ELF, /* a real ELF shared module */
|
||||||
DMT_PE, /* a native or builtin PE module */
|
DMT_PE, /* a native or builtin PE module */
|
||||||
|
DMT_PDB, /* PDB file */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct module
|
struct module
|
||||||
|
@ -295,6 +296,7 @@ extern HANDLE hMsvcrt;
|
||||||
/* elf_module.c */
|
/* elf_module.c */
|
||||||
typedef BOOL (*elf_enum_modules_cb)(const char*, unsigned long addr, void* user);
|
typedef BOOL (*elf_enum_modules_cb)(const char*, unsigned long addr, void* user);
|
||||||
extern BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb, void*);
|
extern BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb, void*);
|
||||||
|
extern BOOL elf_fetch_file_info(const char* name, DWORD* base, DWORD* size, DWORD* checksum);
|
||||||
struct elf_file_map;
|
struct elf_file_map;
|
||||||
extern BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap);
|
extern BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap);
|
||||||
extern struct module*
|
extern struct module*
|
||||||
|
@ -324,6 +326,8 @@ extern struct module*
|
||||||
extern struct module*
|
extern struct module*
|
||||||
module_get_containee(const struct process* pcs,
|
module_get_containee(const struct process* pcs,
|
||||||
const struct module* inner);
|
const struct module* inner);
|
||||||
|
extern enum module_type
|
||||||
|
module_get_type_by_name(const char* name);
|
||||||
extern void module_reset_debug_info(struct module* module);
|
extern void module_reset_debug_info(struct module* module);
|
||||||
extern BOOL module_remove(struct process* pcs,
|
extern BOOL module_remove(struct process* pcs,
|
||||||
struct module* module);
|
struct module* module);
|
||||||
|
@ -334,6 +338,7 @@ extern BOOL pe_load_debug_directory(const struct process* pcs,
|
||||||
const IMAGE_SECTION_HEADER* sectp, DWORD nsect,
|
const IMAGE_SECTION_HEADER* sectp, DWORD nsect,
|
||||||
const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg);
|
const IMAGE_DEBUG_DIRECTORY* dbg, int nDbg);
|
||||||
/* pe_module.c */
|
/* pe_module.c */
|
||||||
|
extern BOOL pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth);
|
||||||
extern struct module*
|
extern struct module*
|
||||||
pe_load_module(struct process* pcs, char* name,
|
pe_load_module(struct process* pcs, char* name,
|
||||||
HANDLE hFile, DWORD base, DWORD size);
|
HANDLE hFile, DWORD base, DWORD size);
|
||||||
|
|
|
@ -81,12 +81,14 @@ struct elf_module_info
|
||||||
|
|
||||||
#define ELF_INFO_DEBUG_HEADER 0x0001
|
#define ELF_INFO_DEBUG_HEADER 0x0001
|
||||||
#define ELF_INFO_MODULE 0x0002
|
#define ELF_INFO_MODULE 0x0002
|
||||||
|
#define ELF_INFO_NAME 0x0004
|
||||||
|
|
||||||
struct elf_info
|
struct elf_info
|
||||||
{
|
{
|
||||||
unsigned flags; /* IN one (or several) of the ELF_INFO constants */
|
unsigned flags; /* IN one (or several) of the ELF_INFO constants */
|
||||||
unsigned long dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
|
unsigned long dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
|
||||||
struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */
|
struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */
|
||||||
|
const char* module_name; /* OUT found module name (if ELF_INFO_NAME is set) */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NO_MAP ((const void*)0xffffffff)
|
#define NO_MAP ((const void*)0xffffffff)
|
||||||
|
@ -139,7 +141,8 @@ static const char* elf_map_section(struct elf_file_map* fmap, int sidx)
|
||||||
return NO_MAP;
|
return NO_MAP;
|
||||||
/* align required information on page size (we assume pagesize is a power of 2) */
|
/* align required information on page size (we assume pagesize is a power of 2) */
|
||||||
ofst = fmap->sect[sidx].shdr.sh_offset & ~(pgsz - 1);
|
ofst = fmap->sect[sidx].shdr.sh_offset & ~(pgsz - 1);
|
||||||
size = (fmap->sect[sidx].shdr.sh_offset + fmap->sect[sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1);
|
size = (fmap->sect[sidx].shdr.sh_offset +
|
||||||
|
fmap->sect[sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1);
|
||||||
fmap->sect[sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fmap->fd, ofst);
|
fmap->sect[sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fmap->fd, ofst);
|
||||||
if (fmap->sect[sidx].mapped == NO_MAP) return NO_MAP;
|
if (fmap->sect[sidx].mapped == NO_MAP) return NO_MAP;
|
||||||
return fmap->sect[sidx].mapped + (fmap->sect[sidx].shdr.sh_offset & (pgsz - 1));
|
return fmap->sect[sidx].mapped + (fmap->sect[sidx].shdr.sh_offset & (pgsz - 1));
|
||||||
|
@ -188,7 +191,8 @@ static BOOL elf_map_file(const char* filename, struct elf_file_map* fmap)
|
||||||
if (memcmp(fmap->elfhdr.e_ident,
|
if (memcmp(fmap->elfhdr.e_ident,
|
||||||
elf_signature, sizeof(elf_signature))) return FALSE;
|
elf_signature, sizeof(elf_signature))) return FALSE;
|
||||||
|
|
||||||
fmap->sect = HeapAlloc(GetProcessHeap(), 0, fmap->elfhdr.e_shnum * sizeof(fmap->sect[0]));
|
fmap->sect = HeapAlloc(GetProcessHeap(), 0,
|
||||||
|
fmap->elfhdr.e_shnum * sizeof(fmap->sect[0]));
|
||||||
if (!fmap->sect) return FALSE;
|
if (!fmap->sect) return FALSE;
|
||||||
|
|
||||||
lseek(fmap->fd, fmap->elfhdr.e_shoff, SEEK_SET);
|
lseek(fmap->fd, fmap->elfhdr.e_shoff, SEEK_SET);
|
||||||
|
@ -800,7 +804,8 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
shstrtab = elf_map_section(fmap, fmap->elfhdr.e_shstrndx);
|
shstrtab = elf_map_section(fmap, fmap->elfhdr.e_shstrndx);
|
||||||
if (shstrtab == NO_MAP) return FALSE;
|
if (shstrtab == NO_MAP) return FALSE;
|
||||||
|
|
||||||
symtab_sect = dynsym_sect = stab_sect = stabstr_sect = debug_sect = debuglink_sect = -1;
|
symtab_sect = dynsym_sect = stab_sect = stabstr_sect =
|
||||||
|
debug_sect = debuglink_sect = -1;
|
||||||
|
|
||||||
for (i = 0; i < fmap->elfhdr.e_shnum; i++)
|
for (i = 0; i < fmap->elfhdr.e_shnum; i++)
|
||||||
{
|
{
|
||||||
|
@ -867,7 +872,8 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
else if (debug_sect != -1)
|
else if (debug_sect != -1)
|
||||||
{
|
{
|
||||||
/* Dwarf 2 debug information */
|
/* Dwarf 2 debug information */
|
||||||
FIXME("Unsupported Dwarf2 information for %s\n", module->module.ModuleName);
|
FIXME("Unsupported Dwarf2 information for %s\n",
|
||||||
|
module->module.ModuleName);
|
||||||
}
|
}
|
||||||
else if (debuglink_sect != -1)
|
else if (debuglink_sect != -1)
|
||||||
{
|
{
|
||||||
|
@ -876,7 +882,8 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
|
|
||||||
dbg_link = elf_map_section(fmap, debuglink_sect);
|
dbg_link = elf_map_section(fmap, debuglink_sect);
|
||||||
/* The content of a debug link section is:
|
/* The content of a debug link section is:
|
||||||
* 1/ a NULL terminated string, containing the file name for the debug info
|
* 1/ a NULL terminated string, containing the file name for the
|
||||||
|
* debug info
|
||||||
* 2/ padding on 4 byte boundary
|
* 2/ padding on 4 byte boundary
|
||||||
* 3/ CRC of the linked ELF file
|
* 3/ CRC of the linked ELF file
|
||||||
*/
|
*/
|
||||||
|
@ -884,11 +891,14 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
|
||||||
{
|
{
|
||||||
fmap_link.crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3));
|
fmap_link.crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3));
|
||||||
fmap_link.with_crc = 1;
|
fmap_link.with_crc = 1;
|
||||||
ret = elf_load_debug_info_from_map(module, &fmap_link, pool, ht_symtab);
|
ret = elf_load_debug_info_from_map(module, &fmap_link, pool,
|
||||||
|
ht_symtab);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
WARN("Couldn't load debug information from %s\n", dbg_link);
|
WARN("Couldn't load debug information from %s\n", dbg_link);
|
||||||
}
|
}
|
||||||
else WARN("Couldn't load linked debug file for %s\n", module->module.ModuleName);
|
else
|
||||||
|
WARN("Couldn't load linked debug file for %s\n",
|
||||||
|
module->module.ModuleName);
|
||||||
elf_unmap_file(&fmap_link);
|
elf_unmap_file(&fmap_link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -940,6 +950,22 @@ BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* elf_fetch_file_info
|
||||||
|
*
|
||||||
|
* Gathers some more information for an ELF module from a given file
|
||||||
|
*/
|
||||||
|
BOOL elf_fetch_file_info(const char* name, DWORD* base,
|
||||||
|
DWORD* size, DWORD* checksum)
|
||||||
|
{
|
||||||
|
struct elf_file_map fmap;
|
||||||
|
if (!elf_map_file(name, &fmap)) return FALSE;
|
||||||
|
if (base) *base = fmap.elf_start;
|
||||||
|
*size = fmap.elf_size;
|
||||||
|
*checksum = calc_crc32(&fmap);
|
||||||
|
elf_unmap_file(&fmap);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* is_dt_flag_valid
|
* is_dt_flag_valid
|
||||||
|
@ -1033,7 +1059,7 @@ static BOOL elf_load_file(struct process* pcs, const char* filename,
|
||||||
if (!elf_module_info) goto leave;
|
if (!elf_module_info) goto leave;
|
||||||
elf_info->module = module_new(pcs, filename, DMT_ELF,
|
elf_info->module = module_new(pcs, filename, DMT_ELF,
|
||||||
(load_offset) ? load_offset : fmap.elf_start,
|
(load_offset) ? load_offset : fmap.elf_start,
|
||||||
fmap.elf_size, 0, 0);
|
fmap.elf_size, 0, calc_crc32(&fmap));
|
||||||
if (!elf_info->module)
|
if (!elf_info->module)
|
||||||
{
|
{
|
||||||
HeapFree(GetProcessHeap(), 0, elf_module_info);
|
HeapFree(GetProcessHeap(), 0, elf_module_info);
|
||||||
|
@ -1053,6 +1079,11 @@ static BOOL elf_load_file(struct process* pcs, const char* filename,
|
||||||
elf_info->module->elf_info->elf_loader = 0;
|
elf_info->module->elf_info->elf_loader = 0;
|
||||||
} else ret = TRUE;
|
} else ret = TRUE;
|
||||||
|
|
||||||
|
if (elf_info->flags & ELF_INFO_NAME)
|
||||||
|
{
|
||||||
|
elf_info->module_name = strcpy(HeapAlloc(GetProcessHeap(), 0,
|
||||||
|
strlen(filename) + 1), filename);
|
||||||
|
}
|
||||||
leave:
|
leave:
|
||||||
elf_unmap_file(&fmap);
|
elf_unmap_file(&fmap);
|
||||||
|
|
||||||
|
@ -1137,6 +1168,7 @@ static BOOL elf_search_and_load_file(struct process* pcs, const char* filename,
|
||||||
* Enumerate ELF modules from a running process
|
* Enumerate ELF modules from a running process
|
||||||
*/
|
*/
|
||||||
static BOOL elf_enum_modules_internal(const struct process* pcs,
|
static BOOL elf_enum_modules_internal(const struct process* pcs,
|
||||||
|
const char* main_name,
|
||||||
elf_enum_modules_cb cb, void* user)
|
elf_enum_modules_cb cb, void* user)
|
||||||
{
|
{
|
||||||
struct r_debug dbg_hdr;
|
struct r_debug dbg_hdr;
|
||||||
|
@ -1164,7 +1196,8 @@ static BOOL elf_enum_modules_internal(const struct process* pcs,
|
||||||
ReadProcessMemory(pcs->handle, lm.l_name, bufstr, sizeof(bufstr), NULL))
|
ReadProcessMemory(pcs->handle, lm.l_name, bufstr, sizeof(bufstr), NULL))
|
||||||
{
|
{
|
||||||
bufstr[sizeof(bufstr) - 1] = '\0';
|
bufstr[sizeof(bufstr) - 1] = '\0';
|
||||||
if (!cb(bufstr, lm.l_addr, user)) break;
|
if (main_name && !bufstr[0]) strcpy(bufstr, main_name);
|
||||||
|
if (!cb(bufstr, (unsigned long)lm.l_addr, user)) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1204,7 +1237,7 @@ BOOL elf_synchronize_module_list(struct process* pcs)
|
||||||
|
|
||||||
es.pcs = pcs;
|
es.pcs = pcs;
|
||||||
es.elf_info.flags = ELF_INFO_MODULE;
|
es.elf_info.flags = ELF_INFO_MODULE;
|
||||||
if (!elf_enum_modules_internal(pcs, elf_enum_sync_cb, &es))
|
if (!elf_enum_modules_internal(pcs, NULL, elf_enum_sync_cb, &es))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
module = pcs->lmodules;
|
module = pcs->lmodules;
|
||||||
|
@ -1277,13 +1310,16 @@ BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb cb, void* user)
|
||||||
{
|
{
|
||||||
struct process pcs;
|
struct process pcs;
|
||||||
struct elf_info elf_info;
|
struct elf_info elf_info;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
memset(&pcs, 0, sizeof(pcs));
|
memset(&pcs, 0, sizeof(pcs));
|
||||||
pcs.handle = hProc;
|
pcs.handle = hProc;
|
||||||
elf_info.flags = ELF_INFO_DEBUG_HEADER;
|
elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_NAME;
|
||||||
if (!elf_search_loader(&pcs, &elf_info)) return FALSE;
|
if (!elf_search_loader(&pcs, &elf_info)) return FALSE;
|
||||||
pcs.dbg_hdr_addr = elf_info.dbg_hdr_addr;
|
pcs.dbg_hdr_addr = elf_info.dbg_hdr_addr;
|
||||||
return elf_enum_modules_internal(&pcs, cb, user);
|
ret = elf_enum_modules_internal(&pcs, elf_info.module_name, cb, user);
|
||||||
|
HeapFree(GetProcessHeap(), 0, (char*)elf_info.module_name);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct elf_load
|
struct elf_load
|
||||||
|
@ -1329,7 +1365,7 @@ struct module* elf_load_module(struct process* pcs, const char* name, DWORD add
|
||||||
{
|
{
|
||||||
struct elf_load el;
|
struct elf_load el;
|
||||||
|
|
||||||
TRACE("(%p %s)\n", pcs, name);
|
TRACE("(%p %s %08lx)\n", pcs, name, addr);
|
||||||
|
|
||||||
el.elf_info.flags = ELF_INFO_MODULE;
|
el.elf_info.flags = ELF_INFO_MODULE;
|
||||||
el.ret = FALSE;
|
el.ret = FALSE;
|
||||||
|
@ -1337,14 +1373,14 @@ struct module* elf_load_module(struct process* pcs, const char* name, DWORD add
|
||||||
if (pcs->dbg_hdr_addr) /* we're debugging a life target */
|
if (pcs->dbg_hdr_addr) /* we're debugging a life target */
|
||||||
{
|
{
|
||||||
el.pcs = pcs;
|
el.pcs = pcs;
|
||||||
/* do only the lookup from the filename, not the path (as we lookup module name
|
/* do only the lookup from the filename, not the path (as we lookup module
|
||||||
* in the process' loaded module list)
|
* name in the process' loaded module list)
|
||||||
*/
|
*/
|
||||||
el.name = strrchr(name, '/');
|
el.name = strrchr(name, '/');
|
||||||
if (!el.name++) el.name = name;
|
if (!el.name++) el.name = name;
|
||||||
el.ret = FALSE;
|
el.ret = FALSE;
|
||||||
|
|
||||||
if (!elf_enum_modules_internal(pcs, elf_load_cb, &el))
|
if (!elf_enum_modules_internal(pcs, NULL, elf_load_cb, &el))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (addr)
|
else if (addr)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* File minidump.c - management of dumps (read & write)
|
* File minidump.c - management of dumps (read & write)
|
||||||
*
|
*
|
||||||
* Copyright (C) 2004, Eric Pouech
|
* Copyright (C) 2004-2005, Eric Pouech
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -45,6 +45,8 @@ struct dump_module
|
||||||
unsigned is_elf;
|
unsigned is_elf;
|
||||||
ULONG base;
|
ULONG base;
|
||||||
ULONG size;
|
ULONG size;
|
||||||
|
DWORD timestamp;
|
||||||
|
DWORD checksum;
|
||||||
char name[MAX_PATH];
|
char name[MAX_PATH];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -182,12 +184,15 @@ static BOOL fetch_thread_info(struct dump_context* dc, int thd_idx,
|
||||||
* Add a module to a dump context
|
* Add a module to a dump context
|
||||||
*/
|
*/
|
||||||
static BOOL add_module(struct dump_context* dc, const char* name,
|
static BOOL add_module(struct dump_context* dc, const char* name,
|
||||||
DWORD base, DWORD size, BOOL is_elf)
|
DWORD base, DWORD size, DWORD timestamp, DWORD checksum,
|
||||||
|
BOOL is_elf)
|
||||||
{
|
{
|
||||||
if (!dc->module)
|
if (!dc->module)
|
||||||
dc->module = HeapAlloc(GetProcessHeap(), 0, ++dc->num_module * sizeof(*dc->module));
|
dc->module = HeapAlloc(GetProcessHeap(), 0,
|
||||||
|
++dc->num_module * sizeof(*dc->module));
|
||||||
else
|
else
|
||||||
dc->module = HeapReAlloc(GetProcessHeap(), 0, dc->module, ++dc->num_module * sizeof(*dc->module));
|
dc->module = HeapReAlloc(GetProcessHeap(), 0, dc->module,
|
||||||
|
++dc->num_module * sizeof(*dc->module));
|
||||||
if (!dc->module) return FALSE;
|
if (!dc->module) return FALSE;
|
||||||
if (is_elf ||
|
if (is_elf ||
|
||||||
!GetModuleFileNameExA(dc->hProcess, (HMODULE)base,
|
!GetModuleFileNameExA(dc->hProcess, (HMODULE)base,
|
||||||
|
@ -197,6 +202,8 @@ static BOOL add_module(struct dump_context* dc, const char* name,
|
||||||
sizeof(dc->module[dc->num_module - 1].name));
|
sizeof(dc->module[dc->num_module - 1].name));
|
||||||
dc->module[dc->num_module - 1].base = base;
|
dc->module[dc->num_module - 1].base = base;
|
||||||
dc->module[dc->num_module - 1].size = size;
|
dc->module[dc->num_module - 1].size = size;
|
||||||
|
dc->module[dc->num_module - 1].timestamp = timestamp;
|
||||||
|
dc->module[dc->num_module - 1].checksum = checksum;
|
||||||
dc->module[dc->num_module - 1].is_elf = is_elf;
|
dc->module[dc->num_module - 1].is_elf = is_elf;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -210,7 +217,14 @@ static BOOL add_module(struct dump_context* dc, const char* name,
|
||||||
static BOOL WINAPI fetch_pe_module_info_cb(char* name, DWORD base, DWORD size,
|
static BOOL WINAPI fetch_pe_module_info_cb(char* name, DWORD base, DWORD size,
|
||||||
void* user)
|
void* user)
|
||||||
{
|
{
|
||||||
return add_module((struct dump_context*)user, name, base, size, FALSE);
|
struct dump_context* dc = (struct dump_context*)user;
|
||||||
|
IMAGE_NT_HEADERS nth;
|
||||||
|
|
||||||
|
if (pe_load_nt_header(dc->hProcess, base, &nth))
|
||||||
|
add_module((struct dump_context*)user, name, base, size,
|
||||||
|
nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum,
|
||||||
|
FALSE);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
@ -221,13 +235,22 @@ static BOOL WINAPI fetch_pe_module_info_cb(char* name, DWORD base, DWORD size,
|
||||||
static BOOL fetch_elf_module_info_cb(const char* name, unsigned long base,
|
static BOOL fetch_elf_module_info_cb(const char* name, unsigned long base,
|
||||||
void* user)
|
void* user)
|
||||||
{
|
{
|
||||||
return add_module((struct dump_context*)user, name,
|
struct dump_context* dc = (struct dump_context*)user;
|
||||||
base, 0 /* FIXME */, TRUE);
|
DWORD size, checksum;
|
||||||
|
|
||||||
|
/* FIXME: there's no relevant timestamp on ELF modules */
|
||||||
|
/* NB: if we have a non-null base from the live-target use it (whenever
|
||||||
|
* the ELF module is relocatable or not). If we have a null base (ELF
|
||||||
|
* module isn't relocatable) then grab its base address from ELF file
|
||||||
|
*/
|
||||||
|
if (!elf_fetch_file_info(name, base ? NULL : &base, &size, &checksum))
|
||||||
|
size = checksum = 0;
|
||||||
|
add_module(dc, name, base, size, 0 /* FIXME */, checksum, TRUE);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fetch_module_info(struct dump_context* dc)
|
static void fetch_module_info(struct dump_context* dc)
|
||||||
{
|
{
|
||||||
WINE_FIXME("--> %p\n", dc->hProcess);
|
|
||||||
EnumerateLoadedModules(dc->hProcess, fetch_pe_module_info_cb, dc);
|
EnumerateLoadedModules(dc->hProcess, fetch_pe_module_info_cb, dc);
|
||||||
/* Since we include ELF modules in a separate stream from the regular PE ones,
|
/* Since we include ELF modules in a separate stream from the regular PE ones,
|
||||||
* we can always include those ELF modules (they don't eat lots of space)
|
* we can always include those ELF modules (they don't eat lots of space)
|
||||||
|
@ -352,7 +375,8 @@ static void dump_modules(struct dump_context* dc, BOOL dump_elf)
|
||||||
|
|
||||||
for (i = nmod = 0; i < dc->num_module; i++)
|
for (i = nmod = 0; i < dc->num_module; i++)
|
||||||
{
|
{
|
||||||
if ((dc->module[i].is_elf && dump_elf) || (!dc->module[i].is_elf && !dump_elf))
|
if ((dc->module[i].is_elf && dump_elf) ||
|
||||||
|
(!dc->module[i].is_elf && !dump_elf))
|
||||||
nmod++;
|
nmod++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +390,8 @@ static void dump_modules(struct dump_context* dc, BOOL dump_elf)
|
||||||
dc->rva += sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * nmod;
|
dc->rva += sizeof(mdModuleList.NumberOfModules) + sizeof(mdModule) * nmod;
|
||||||
for (i = 0; i < dc->num_module; i++)
|
for (i = 0; i < dc->num_module; i++)
|
||||||
{
|
{
|
||||||
if ((dc->module[i].is_elf && !dump_elf) || (!dc->module[i].is_elf && dump_elf))
|
if ((dc->module[i].is_elf && !dump_elf) ||
|
||||||
|
(!dc->module[i].is_elf && dump_elf))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
flags_out = ModuleWriteModule | ModuleWriteMiscRecord | ModuleWriteCvRecord;
|
flags_out = ModuleWriteModule | ModuleWriteMiscRecord | ModuleWriteCvRecord;
|
||||||
|
@ -396,8 +421,8 @@ static void dump_modules(struct dump_context* dc, BOOL dump_elf)
|
||||||
cbin.u.Module.FullPath = ms->Buffer;
|
cbin.u.Module.FullPath = ms->Buffer;
|
||||||
cbin.u.Module.BaseOfImage = dc->module[i].base;
|
cbin.u.Module.BaseOfImage = dc->module[i].base;
|
||||||
cbin.u.Module.SizeOfImage = dc->module[i].size;
|
cbin.u.Module.SizeOfImage = dc->module[i].size;
|
||||||
cbin.u.Module.CheckSum = 0; /* FIXME */
|
cbin.u.Module.CheckSum = dc->module[i].checksum;
|
||||||
cbin.u.Module.TimeDateStamp = 0; /* FIXME */
|
cbin.u.Module.TimeDateStamp = dc->module[i].timestamp;
|
||||||
memset(&cbin.u.Module.VersionInfo, 0, sizeof(cbin.u.Module.VersionInfo));
|
memset(&cbin.u.Module.VersionInfo, 0, sizeof(cbin.u.Module.VersionInfo));
|
||||||
cbin.u.Module.CvRecord = NULL;
|
cbin.u.Module.CvRecord = NULL;
|
||||||
cbin.u.Module.SizeOfCvRecord = 0;
|
cbin.u.Module.SizeOfCvRecord = 0;
|
||||||
|
@ -413,8 +438,8 @@ static void dump_modules(struct dump_context* dc, BOOL dump_elf)
|
||||||
{
|
{
|
||||||
mdModule.BaseOfImage = dc->module[i].base;
|
mdModule.BaseOfImage = dc->module[i].base;
|
||||||
mdModule.SizeOfImage = dc->module[i].size;
|
mdModule.SizeOfImage = dc->module[i].size;
|
||||||
mdModule.CheckSum = 0; /* FIXME */
|
mdModule.CheckSum = dc->module[i].checksum;
|
||||||
mdModule.TimeDateStamp = 0; /* FIXME */
|
mdModule.TimeDateStamp = dc->module[i].timestamp;
|
||||||
mdModule.ModuleNameRva = dc->rva;
|
mdModule.ModuleNameRva = dc->rva;
|
||||||
ms->Length -= sizeof(WCHAR);
|
ms->Length -= sizeof(WCHAR);
|
||||||
append(dc, ms, sizeof(ULONG) + ms->Length);
|
append(dc, ms, sizeof(ULONG) + ms->Length);
|
||||||
|
@ -619,7 +644,6 @@ static void dump_misc_info(struct dump_context* dc)
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* MiniDumpWriteDump (DEBUGHLP.@)
|
* MiniDumpWriteDump (DEBUGHLP.@)
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, HANDLE hFile,
|
BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD pid, HANDLE hFile,
|
||||||
MINIDUMP_TYPE DumpType,
|
MINIDUMP_TYPE DumpType,
|
||||||
|
|
|
@ -76,6 +76,7 @@ struct module* module_new(struct process* pcs, const char* name,
|
||||||
{
|
{
|
||||||
struct module* module;
|
struct module* module;
|
||||||
|
|
||||||
|
assert(type == DMT_ELF || type == DMT_PE);
|
||||||
if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
|
if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -93,7 +94,8 @@ struct module* module_new(struct process* pcs, const char* name,
|
||||||
module->module.SizeOfStruct = sizeof(module->module);
|
module->module.SizeOfStruct = sizeof(module->module);
|
||||||
module->module.BaseOfImage = mod_addr;
|
module->module.BaseOfImage = mod_addr;
|
||||||
module->module.ImageSize = size;
|
module->module.ImageSize = size;
|
||||||
module_fill_module(name, module->module.ModuleName, sizeof(module->module.ModuleName));
|
module_fill_module(name, module->module.ModuleName,
|
||||||
|
sizeof(module->module.ModuleName));
|
||||||
module->module.ImageName[0] = '\0';
|
module->module.ImageName[0] = '\0';
|
||||||
lstrcpynA(module->module.LoadedImageName, name, sizeof(module->module.LoadedImageName));
|
lstrcpynA(module->module.LoadedImageName, name, sizeof(module->module.LoadedImageName));
|
||||||
module->module.SymType = SymNone;
|
module->module.SymType = SymNone;
|
||||||
|
@ -139,13 +141,15 @@ struct module* module_find_by_name(const struct process* pcs,
|
||||||
|
|
||||||
for (module = pcs->lmodules; module; module = module->next)
|
for (module = pcs->lmodules; module; module = module->next)
|
||||||
{
|
{
|
||||||
if (type == module->type && !strcasecmp(name, module->module.LoadedImageName))
|
if (type == module->type &&
|
||||||
|
!strcasecmp(name, module->module.LoadedImageName))
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
module_fill_module(name, modname, sizeof(modname));
|
module_fill_module(name, modname, sizeof(modname));
|
||||||
for (module = pcs->lmodules; module; module = module->next)
|
for (module = pcs->lmodules; module; module = module->next)
|
||||||
{
|
{
|
||||||
if (type == module->type && !strcasecmp(modname, module->module.ModuleName))
|
if (type == module->type &&
|
||||||
|
!strcasecmp(modname, module->module.ModuleName))
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,31 +285,34 @@ static BOOL module_is_elf_container_loaded(struct process* pcs, const char* Imag
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL elf_is_shared_by_name(const char* name)
|
/******************************************************************
|
||||||
|
* module_get_type_by_name
|
||||||
|
*
|
||||||
|
* Guesses a filename type from its extension
|
||||||
|
*/
|
||||||
|
enum module_type module_get_type_by_name(const char* name)
|
||||||
{
|
{
|
||||||
const char* ptr;
|
const char* ptr;
|
||||||
int len = strlen(name);
|
int len = strlen(name);
|
||||||
|
|
||||||
/* check for terminating .so or .so.[digit]+ */
|
/* check for terminating .so or .so.[digit] */
|
||||||
while (len)
|
ptr = strrchr(name, '.');
|
||||||
|
if (ptr)
|
||||||
{
|
{
|
||||||
for (ptr = name + len - 1; ptr >= name; ptr--) if (*ptr == '.') break;
|
if (!strcmp(ptr, ".so") ||
|
||||||
if (ptr < name) break;
|
(isdigit(ptr[1]) && !ptr[2] && ptr >= name + 3 && !memcmp(ptr - 3, ".so", 3)))
|
||||||
if (ptr == name + len - 2 && isdigit(ptr[1]))
|
return DMT_ELF;
|
||||||
{
|
else if (!strcasecmp(ptr, ".pdb"))
|
||||||
len -= 2;
|
return DMT_PDB;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (ptr == name + len - 3 && ptr[1] == 's' && ptr[2] == 'o')
|
/* wine-[kp]thread is also an ELF module */
|
||||||
return TRUE;
|
else if (((len > 12 && name[len - 13] == '/') || len == 12) &&
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* wine-[kp]thread is valid too */
|
|
||||||
if (((len > 12 && name[len - 13] == '/') || len == 12) &&
|
|
||||||
(!strcasecmp(name + len - 12, "wine-pthread") ||
|
(!strcasecmp(name + len - 12, "wine-pthread") ||
|
||||||
!strcasecmp(name + len - 12, "wine-kthread")))
|
!strcasecmp(name + len - 12, "wine-kthread")))
|
||||||
return TRUE;
|
{
|
||||||
return FALSE;
|
return DMT_ELF;
|
||||||
|
}
|
||||||
|
return DMT_PE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -333,7 +340,8 @@ DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
|
||||||
if (module_is_elf_container_loaded(pcs, ImageName, ModuleName))
|
if (module_is_elf_container_loaded(pcs, ImageName, ModuleName))
|
||||||
{
|
{
|
||||||
/* force the loading of DLL as builtin */
|
/* force the loading of DLL as builtin */
|
||||||
if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
|
if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName,
|
||||||
|
BaseOfDll, SizeOfDll)))
|
||||||
goto done;
|
goto done;
|
||||||
WARN("Couldn't locate %s\n", ImageName);
|
WARN("Couldn't locate %s\n", ImageName);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -341,12 +349,13 @@ DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
|
||||||
TRACE("Assuming %s as native DLL\n", ImageName);
|
TRACE("Assuming %s as native DLL\n", ImageName);
|
||||||
if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
|
if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
|
||||||
{
|
{
|
||||||
if (elf_is_shared_by_name(ImageName) &&
|
if (module_get_type_by_name(ImageName) == DMT_ELF &&
|
||||||
(module = elf_load_module(pcs, ImageName, BaseOfDll)))
|
(module = elf_load_module(pcs, ImageName, BaseOfDll)))
|
||||||
goto done;
|
goto done;
|
||||||
FIXME("Should have successfully loaded debug information for image %s\n",
|
FIXME("Should have successfully loaded debug information for image %s\n",
|
||||||
ImageName);
|
ImageName);
|
||||||
if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
|
if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName,
|
||||||
|
BaseOfDll, SizeOfDll)))
|
||||||
goto done;
|
goto done;
|
||||||
WARN("Couldn't locate %s\n", ImageName);
|
WARN("Couldn't locate %s\n", ImageName);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -461,7 +470,6 @@ BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess,
|
||||||
!GetModuleBaseNameA(hProcess, hMods[i], base, sizeof(base)))
|
!GetModuleBaseNameA(hProcess, hMods[i], base, sizeof(base)))
|
||||||
continue;
|
continue;
|
||||||
module_fill_module(base, mod, sizeof(mod));
|
module_fill_module(base, mod, sizeof(mod));
|
||||||
|
|
||||||
EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage,
|
EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage,
|
||||||
UserContext);
|
UserContext);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "dbghelp_private.h"
|
#include "dbghelp_private.h"
|
||||||
|
#include "ntstatus.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "winternl.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||||
|
@ -140,7 +144,7 @@ BOOL WINAPI SymMatchFileName(char* file, char* match,
|
||||||
return mptr == match - 1;
|
return mptr == match - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL do_search(const char* file, char* buffer,
|
static BOOL do_search(const char* file, char* buffer, BOOL recurse,
|
||||||
PENUMDIRTREE_CALLBACK cb, void* user)
|
PENUMDIRTREE_CALLBACK cb, void* user)
|
||||||
{
|
{
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
|
@ -161,8 +165,8 @@ static BOOL do_search(const char* file, char* buffer,
|
||||||
if (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")) continue;
|
if (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")) continue;
|
||||||
|
|
||||||
strcpy(buffer + pos, fd.cFileName);
|
strcpy(buffer + pos, fd.cFileName);
|
||||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
if (recurse && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||||
found = do_search(file, buffer, cb, user);
|
found = do_search(file, buffer, TRUE, cb, user);
|
||||||
else if (SymMatchFileName(buffer, (char*)file, NULL, NULL))
|
else if (SymMatchFileName(buffer, (char*)file, NULL, NULL))
|
||||||
{
|
{
|
||||||
if (!cb || cb(buffer, user)) found = TRUE;
|
if (!cb || cb(buffer, user)) found = TRUE;
|
||||||
|
@ -182,7 +186,7 @@ BOOL WINAPI SearchTreeForFile(LPSTR root, LPSTR file, LPSTR buffer)
|
||||||
TRACE("(%s, %s, %p)\n",
|
TRACE("(%s, %s, %p)\n",
|
||||||
debugstr_a(root), debugstr_a(file), buffer);
|
debugstr_a(root), debugstr_a(file), buffer);
|
||||||
strcpy(buffer, root);
|
strcpy(buffer, root);
|
||||||
return do_search(file, buffer, NULL, NULL);
|
return do_search(file, buffer, TRUE, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
|
@ -196,11 +200,19 @@ BOOL WINAPI EnumDirTree(HANDLE hProcess, PCSTR root, PCSTR file,
|
||||||
TRACE("(%p %s %s %p %p %p)\n", hProcess, root, file, buffer, cb, user);
|
TRACE("(%p %s %s %p %p %p)\n", hProcess, root, file, buffer, cb, user);
|
||||||
|
|
||||||
strcpy(buffer, root);
|
strcpy(buffer, root);
|
||||||
return do_search(file, buffer, cb, user);
|
return do_search(file, buffer, TRUE, cb, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sffip
|
struct sffip
|
||||||
{
|
{
|
||||||
|
enum module_type kind;
|
||||||
|
/* pe: id -> DWORD:timestamp
|
||||||
|
* two -> size of image (from PE header)
|
||||||
|
* pdb: id -> PDB signature
|
||||||
|
* I think either DWORD:timestamp or GUID:guid depending on PDB version
|
||||||
|
* two -> PDB age ???
|
||||||
|
* elf: id -> DWORD:CRC 32 of ELF image (Wine only)
|
||||||
|
*/
|
||||||
PVOID id;
|
PVOID id;
|
||||||
DWORD two;
|
DWORD two;
|
||||||
DWORD three;
|
DWORD three;
|
||||||
|
@ -212,11 +224,66 @@ struct sffip
|
||||||
static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* user)
|
static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* user)
|
||||||
{
|
{
|
||||||
struct sffip* s = (struct sffip*)user;
|
struct sffip* s = (struct sffip*)user;
|
||||||
|
DWORD size, checksum;
|
||||||
|
DWORD_PTR timestamp;
|
||||||
/* FIXME: should check that id/two/three match the file pointed
|
/* FIXME: should check that id/two/three match the file pointed
|
||||||
* by buffer
|
* by buffer
|
||||||
*/
|
*/
|
||||||
/* yes, EnumDirTree and SymFindFileInPath callbacks use the opposite
|
switch (s->kind)
|
||||||
|
{
|
||||||
|
case DMT_PE:
|
||||||
|
{
|
||||||
|
HANDLE hFile, hMap;
|
||||||
|
void* mapping;
|
||||||
|
|
||||||
|
timestamp = ~(DWORD_PTR)s->id;
|
||||||
|
size = ~s->two;
|
||||||
|
hFile = CreateFileA(buffer, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE) return TRUE;
|
||||||
|
if ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL)
|
||||||
|
{
|
||||||
|
if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
|
||||||
|
{
|
||||||
|
IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping);
|
||||||
|
timestamp = nth->FileHeader.TimeDateStamp;
|
||||||
|
size = nth->OptionalHeader.SizeOfImage;
|
||||||
|
UnmapViewOfFile(mapping);
|
||||||
|
}
|
||||||
|
CloseHandle(hMap);
|
||||||
|
}
|
||||||
|
CloseHandle(hFile);
|
||||||
|
if (timestamp != (DWORD_PTR)s->id || size != s->two)
|
||||||
|
{
|
||||||
|
WARN("Found %s, but wrong size or timestamp\n", buffer);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DMT_ELF:
|
||||||
|
if (elf_fetch_file_info(buffer, 0, &size, &checksum))
|
||||||
|
{
|
||||||
|
if (checksum != (DWORD_PTR)s->id)
|
||||||
|
{
|
||||||
|
WARN("Found %s, but wrong checksums: %08lx %08lx\n",
|
||||||
|
buffer, checksum, (DWORD_PTR)s->id);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WARN("Couldn't read %s\n", buffer);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DMT_PDB:
|
||||||
|
FIXME("NIY on '%s'\n", buffer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FIXME("What the heck??\n");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
/* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite
|
||||||
* convention to stop/continue enumeration. sigh.
|
* convention to stop/continue enumeration. sigh.
|
||||||
*/
|
*/
|
||||||
return !(s->cb)((char*)buffer, s->user);
|
return !(s->cb)((char*)buffer, s->user);
|
||||||
|
@ -226,7 +293,7 @@ static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* user)
|
||||||
* SymFindFileInPath (DBGHELP.@)
|
* SymFindFileInPath (DBGHELP.@)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR file,
|
BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR full_path,
|
||||||
PVOID id, DWORD two, DWORD three, DWORD flags,
|
PVOID id, DWORD two, DWORD three, DWORD flags,
|
||||||
LPSTR buffer, PFINDFILEINPATHCALLBACK cb,
|
LPSTR buffer, PFINDFILEINPATHCALLBACK cb,
|
||||||
PVOID user)
|
PVOID user)
|
||||||
|
@ -235,9 +302,10 @@ BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR file,
|
||||||
struct process* pcs = process_find_by_handle(hProcess);
|
struct process* pcs = process_find_by_handle(hProcess);
|
||||||
char tmp[MAX_PATH];
|
char tmp[MAX_PATH];
|
||||||
char* ptr;
|
char* ptr;
|
||||||
|
char* filename;
|
||||||
|
|
||||||
TRACE("(%p %s %s %p %08lx %08lx %08lx %p %p %p)\n",
|
TRACE("(%p %s %s %p %08lx %08lx %08lx %p %p %p)\n",
|
||||||
hProcess, searchPath, file, id, two, three, flags,
|
hProcess, searchPath, full_path, id, two, three, flags,
|
||||||
buffer, cb, user);
|
buffer, cb, user);
|
||||||
|
|
||||||
if (!pcs) return FALSE;
|
if (!pcs) return FALSE;
|
||||||
|
@ -250,7 +318,15 @@ BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR file,
|
||||||
s.cb = cb;
|
s.cb = cb;
|
||||||
s.user = user;
|
s.user = user;
|
||||||
|
|
||||||
file = file_name(file);
|
filename = file_name(full_path);
|
||||||
|
s.kind = module_get_type_by_name(filename);
|
||||||
|
|
||||||
|
/* first check full path to file */
|
||||||
|
if (sffip_cb(full_path, &s))
|
||||||
|
{
|
||||||
|
strcpy(buffer, full_path);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
while (searchPath)
|
while (searchPath)
|
||||||
{
|
{
|
||||||
|
@ -266,7 +342,7 @@ BOOL WINAPI SymFindFileInPath(HANDLE hProcess, LPSTR searchPath, LPSTR file,
|
||||||
strcpy(tmp, searchPath);
|
strcpy(tmp, searchPath);
|
||||||
searchPath = NULL;
|
searchPath = NULL;
|
||||||
}
|
}
|
||||||
if (EnumDirTree(hProcess, tmp, file, buffer, sffip_cb, &s)) return TRUE;
|
if (do_search(filename, tmp, FALSE, sffip_cb, &s)) return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -341,7 +341,7 @@ struct module* pe_load_module(struct process* pcs, char* name,
|
||||||
/* FIXME SetLastError */
|
/* FIXME SetLastError */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if ((hFile = FindExecutableImage(name, NULL, loaded_name)) == NULL)
|
if ((hFile = FindExecutableImage(name, pcs->search_path, loaded_name)) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
opened = TRUE;
|
opened = TRUE;
|
||||||
}
|
}
|
||||||
|
@ -380,6 +380,21 @@ struct module* pe_load_module(struct process* pcs, char* name,
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* pe_load_nt_header
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth)
|
||||||
|
{
|
||||||
|
IMAGE_DOS_HEADER dos;
|
||||||
|
|
||||||
|
return ReadProcessMemory(hProc, (char*)base, &dos, sizeof(dos), NULL) &&
|
||||||
|
dos.e_magic == IMAGE_DOS_SIGNATURE &&
|
||||||
|
ReadProcessMemory(hProc, (char*)(base + dos.e_lfanew),
|
||||||
|
nth, sizeof(*nth), NULL) &&
|
||||||
|
nth->Signature == IMAGE_NT_SIGNATURE;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* pe_load_module_from_pcs
|
* pe_load_module_from_pcs
|
||||||
*
|
*
|
||||||
|
@ -408,14 +423,9 @@ struct module* pe_load_module_from_pcs(struct process* pcs, const char* name,
|
||||||
{
|
{
|
||||||
if (pcs->dbg_hdr_addr)
|
if (pcs->dbg_hdr_addr)
|
||||||
{
|
{
|
||||||
IMAGE_DOS_HEADER dos;
|
|
||||||
IMAGE_NT_HEADERS nth;
|
IMAGE_NT_HEADERS nth;
|
||||||
|
|
||||||
if (ReadProcessMemory(pcs->handle, (char*)base, &dos, sizeof(dos), NULL) &&
|
if (pe_load_nt_header(pcs->handle, base, &nth))
|
||||||
dos.e_magic == IMAGE_DOS_SIGNATURE &&
|
|
||||||
ReadProcessMemory(pcs->handle, (char*)(base + dos.e_lfanew),
|
|
||||||
&nth, sizeof(nth), NULL) &&
|
|
||||||
nth.Signature == IMAGE_NT_SIGNATURE)
|
|
||||||
{
|
{
|
||||||
if (!size) size = nth.OptionalHeader.SizeOfImage;
|
if (!size) size = nth.OptionalHeader.SizeOfImage;
|
||||||
module = module_new(pcs, name, DMT_PE, base, size,
|
module = module_new(pcs, name, DMT_PE, base, size,
|
||||||
|
|
|
@ -887,6 +887,35 @@ BOOL WINAPI UnmapDebugInformation(PIMAGE_DEBUG_INFORMATION);
|
||||||
DWORD WINAPI SymGetOptions(void);
|
DWORD WINAPI SymGetOptions(void);
|
||||||
DWORD WINAPI SymSetOptions(DWORD);
|
DWORD WINAPI SymSetOptions(DWORD);
|
||||||
|
|
||||||
|
/* Symbol server bits */
|
||||||
|
typedef BOOL (WINAPI* PSYMBOLSERVERPROC)(LPCSTR, LPCSTR, PVOID, DWORD, DWORD, LPSTR);
|
||||||
|
typedef BOOL (WINAPI* PSYMBOLSERVEROPENPROC)(void);
|
||||||
|
typedef BOOL (WINAPI* PSYMBOLSERVERCLOSEPROC)(void);
|
||||||
|
typedef BOOL (WINAPI* PSYMBOLSERVERSETOPTIONSPROC)(UINT_PTR, ULONG64);
|
||||||
|
typedef BOOL (CALLBACK* PSYMBOLSERVERCALLBACKPROC)(UINT_PTR, ULONG64, ULONG64);
|
||||||
|
typedef UINT_PTR (WINAPI* PSYMBOLSERVERGETOPTIONSPROC)();
|
||||||
|
typedef BOOL (WINAPI* PSYMBOLSERVERPINGPROC)(LPCSTR);
|
||||||
|
|
||||||
|
#define SSRVOPT_CALLBACK 0x0001
|
||||||
|
#define SSRVOPT_DWORD 0x0002
|
||||||
|
#define SSRVOPT_DWORDPTR 0x0004
|
||||||
|
#define SSRVOPT_GUIDPTR 0x0008
|
||||||
|
#define SSRVOPT_OLDGUIDPTR 0x0010
|
||||||
|
#define SSRVOPT_UNATTENDED 0x0020
|
||||||
|
#define SSRVOPT_NOCOPY 0x0040
|
||||||
|
#define SSRVOPT_PARENTWIN 0x0080
|
||||||
|
#define SSRVOPT_PARAMTYPE 0x0100
|
||||||
|
#define SSRVOPT_SECURE 0x0200
|
||||||
|
#define SSRVOPT_TRACE 0x0400
|
||||||
|
#define SSRVOPT_SETCONTEXT 0x0800
|
||||||
|
#define SSRVOPT_PROXY 0x1000
|
||||||
|
#define SSRVOPT_DOWNSTREAM_STORE 0x2000
|
||||||
|
#define SSRVOPT_RESET ((ULONG_PTR)-1)
|
||||||
|
|
||||||
|
#define SSRVACTION_TRACE 1
|
||||||
|
#define SSRVACTION_QUERYCANCEL 2
|
||||||
|
#define SSRVACTION_EVENT 3
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif /* defined(__cplusplus) */
|
#endif /* defined(__cplusplus) */
|
||||||
|
|
Loading…
Reference in New Issue