dbghelp: Move loader search functions to the end of module files.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
724f433f39
commit
f30fdd1822
|
@ -1483,64 +1483,6 @@ static BOOL elf_enum_modules_internal(const struct process* pcs,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* elf_search_loader
|
|
||||||
*
|
|
||||||
* Lookup in a running ELF process the loader, and sets its ELF link
|
|
||||||
* address (for accessing the list of loaded .so libs) in pcs.
|
|
||||||
* If flags is ELF_INFO_MODULE, the module for the loader is also
|
|
||||||
* added as a module into pcs.
|
|
||||||
*/
|
|
||||||
static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info)
|
|
||||||
{
|
|
||||||
WCHAR *loader = get_wine_loader_name(pcs);
|
|
||||||
PROCESS_BASIC_INFORMATION pbi;
|
|
||||||
ULONG_PTR base = 0;
|
|
||||||
BOOL ret;
|
|
||||||
|
|
||||||
if (NtQueryInformationProcess( pcs->handle, ProcessBasicInformation,
|
|
||||||
&pbi, sizeof(pbi), NULL ))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (!pcs->is_64bit)
|
|
||||||
{
|
|
||||||
PEB32 *peb32 = (PEB32 *)pbi.PebBaseAddress;
|
|
||||||
DWORD base32;
|
|
||||||
|
|
||||||
if (!ReadProcessMemory( pcs->handle, &peb32->Reserved[0], &base32,
|
|
||||||
sizeof(base32), NULL ))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
base = base32;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!ReadProcessMemory( pcs->handle, &pbi.PebBaseAddress->Reserved[0],
|
|
||||||
&base, sizeof(base), NULL ))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = elf_search_and_load_file(pcs, loader, base, 0, elf_info);
|
|
||||||
heap_free(loader);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* elf_read_wine_loader_dbg_info
|
|
||||||
*
|
|
||||||
* Try to find a decent wine executable which could have loaded the debuggee
|
|
||||||
*/
|
|
||||||
BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
|
|
||||||
{
|
|
||||||
struct elf_info elf_info;
|
|
||||||
|
|
||||||
elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE;
|
|
||||||
if (!elf_search_loader(pcs, &elf_info)) return FALSE;
|
|
||||||
elf_info.module->format_info[DFI_ELF]->u.elf_info->elf_loader = 1;
|
|
||||||
module_set_module(elf_info.module, S_WineLoaderW);
|
|
||||||
return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct elf_enum_user
|
struct elf_enum_user
|
||||||
{
|
{
|
||||||
enum_modules_cb cb;
|
enum_modules_cb cb;
|
||||||
|
@ -1720,6 +1662,64 @@ BOOL elf_synchronize_module_list(struct process* pcs)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* elf_search_loader
|
||||||
|
*
|
||||||
|
* Lookup in a running ELF process the loader, and sets its ELF link
|
||||||
|
* address (for accessing the list of loaded .so libs) in pcs.
|
||||||
|
* If flags is ELF_INFO_MODULE, the module for the loader is also
|
||||||
|
* added as a module into pcs.
|
||||||
|
*/
|
||||||
|
static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info)
|
||||||
|
{
|
||||||
|
WCHAR *loader = get_wine_loader_name(pcs);
|
||||||
|
PROCESS_BASIC_INFORMATION pbi;
|
||||||
|
ULONG_PTR base = 0;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
if (NtQueryInformationProcess( pcs->handle, ProcessBasicInformation,
|
||||||
|
&pbi, sizeof(pbi), NULL ))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!pcs->is_64bit)
|
||||||
|
{
|
||||||
|
PEB32 *peb32 = (PEB32 *)pbi.PebBaseAddress;
|
||||||
|
DWORD base32;
|
||||||
|
|
||||||
|
if (!ReadProcessMemory( pcs->handle, &peb32->Reserved[0], &base32,
|
||||||
|
sizeof(base32), NULL ))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
base = base32;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ReadProcessMemory( pcs->handle, &pbi.PebBaseAddress->Reserved[0],
|
||||||
|
&base, sizeof(base), NULL ))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = elf_search_and_load_file(pcs, loader, base, 0, elf_info);
|
||||||
|
heap_free(loader);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* elf_read_wine_loader_dbg_info
|
||||||
|
*
|
||||||
|
* Try to find a decent wine executable which could have loaded the debuggee
|
||||||
|
*/
|
||||||
|
BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
|
||||||
|
{
|
||||||
|
struct elf_info elf_info;
|
||||||
|
|
||||||
|
elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE;
|
||||||
|
if (!elf_search_loader(pcs, &elf_info)) return FALSE;
|
||||||
|
elf_info.module->format_info[DFI_ELF]->u.elf_info->elf_loader = 1;
|
||||||
|
module_set_module(elf_info.module, S_WineLoaderW);
|
||||||
|
return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
#else /* !__ELF__ */
|
#else /* !__ELF__ */
|
||||||
|
|
||||||
BOOL elf_map_handle(HANDLE handle, struct image_file_map* fmap)
|
BOOL elf_map_handle(HANDLE handle, struct image_file_map* fmap)
|
||||||
|
|
|
@ -1373,7 +1373,6 @@ static void macho_module_remove(struct process* pcs, struct module_format* modfm
|
||||||
HeapFree(GetProcessHeap(), 0, modfmt);
|
HeapFree(GetProcessHeap(), 0, modfmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* get_dyld_image_info_address
|
* get_dyld_image_info_address
|
||||||
*/
|
*/
|
||||||
|
@ -1729,6 +1728,96 @@ BOOL macho_synchronize_module_list(struct process* pcs)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* macho_enum_modules
|
||||||
|
*
|
||||||
|
* Enumerates the Mach-O loaded modules from a running target (hProc)
|
||||||
|
* This function doesn't require that someone has called SymInitialize
|
||||||
|
* on this very process.
|
||||||
|
*/
|
||||||
|
BOOL macho_enum_modules(struct process* process, enum_modules_cb cb, void* user)
|
||||||
|
{
|
||||||
|
struct macho_info macho_info;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
TRACE("(%p, %p, %p)\n", process->handle, cb, user);
|
||||||
|
macho_info.flags = MACHO_INFO_DEBUG_HEADER | MACHO_INFO_NAME;
|
||||||
|
ret = macho_enum_modules_internal(process, macho_info.module_name, cb, user);
|
||||||
|
HeapFree(GetProcessHeap(), 0, (char*)macho_info.module_name);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct macho_load
|
||||||
|
{
|
||||||
|
struct process* pcs;
|
||||||
|
struct macho_info macho_info;
|
||||||
|
const WCHAR* name;
|
||||||
|
BOOL ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* macho_load_cb
|
||||||
|
*
|
||||||
|
* Callback for macho_load_module, used to walk the list of loaded
|
||||||
|
* modules.
|
||||||
|
*/
|
||||||
|
static BOOL macho_load_cb(const WCHAR* name, unsigned long addr, void* user)
|
||||||
|
{
|
||||||
|
struct macho_load* ml = user;
|
||||||
|
const WCHAR* p;
|
||||||
|
|
||||||
|
TRACE("(%s, 0x%08lx, %p)\n", debugstr_w(name), addr, user);
|
||||||
|
|
||||||
|
/* memcmp is needed for matches when bufstr contains also version information
|
||||||
|
* ml->name: libc.so, name: libc.so.6.0
|
||||||
|
*/
|
||||||
|
p = file_name(name);
|
||||||
|
if (!memcmp(p, ml->name, lstrlenW(ml->name) * sizeof(WCHAR)))
|
||||||
|
{
|
||||||
|
ml->ret = macho_search_and_load_file(ml->pcs, name, addr, &ml->macho_info);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************
|
||||||
|
* macho_load_module
|
||||||
|
*
|
||||||
|
* Loads a Mach-O module and stores it in process' module list.
|
||||||
|
* Also, find module real name and load address from
|
||||||
|
* the real loaded modules list in pcs address space.
|
||||||
|
*/
|
||||||
|
struct module* macho_load_module(struct process* pcs, const WCHAR* name, unsigned long addr)
|
||||||
|
{
|
||||||
|
struct macho_load ml;
|
||||||
|
|
||||||
|
TRACE("(%p/%p, %s, 0x%08lx)\n", pcs, pcs->handle, debugstr_w(name), addr);
|
||||||
|
|
||||||
|
ml.macho_info.flags = MACHO_INFO_MODULE;
|
||||||
|
ml.ret = FALSE;
|
||||||
|
|
||||||
|
if (pcs->dbg_hdr_addr) /* we're debugging a live target */
|
||||||
|
{
|
||||||
|
ml.pcs = pcs;
|
||||||
|
/* do only the lookup from the filename, not the path (as we lookup module
|
||||||
|
* name in the process' loaded module list)
|
||||||
|
*/
|
||||||
|
ml.name = file_name(name);
|
||||||
|
ml.ret = FALSE;
|
||||||
|
|
||||||
|
if (!macho_enum_modules_internal(pcs, NULL, macho_load_cb, &ml))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (addr)
|
||||||
|
{
|
||||||
|
ml.name = name;
|
||||||
|
ml.ret = macho_search_and_load_file(pcs, ml.name, addr, &ml.macho_info);
|
||||||
|
}
|
||||||
|
if (!ml.ret) return NULL;
|
||||||
|
assert(ml.macho_info.module);
|
||||||
|
return ml.macho_info.module;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
* macho_search_loader
|
* macho_search_loader
|
||||||
*
|
*
|
||||||
|
@ -1836,96 +1925,6 @@ BOOL macho_read_wine_loader_dbg_info(struct process* pcs)
|
||||||
return (pcs->dbg_hdr_addr = macho_info.dbg_hdr_addr) != 0;
|
return (pcs->dbg_hdr_addr = macho_info.dbg_hdr_addr) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* macho_enum_modules
|
|
||||||
*
|
|
||||||
* Enumerates the Mach-O loaded modules from a running target (hProc)
|
|
||||||
* This function doesn't require that someone has called SymInitialize
|
|
||||||
* on this very process.
|
|
||||||
*/
|
|
||||||
BOOL macho_enum_modules(struct process* process, enum_modules_cb cb, void* user)
|
|
||||||
{
|
|
||||||
struct macho_info macho_info;
|
|
||||||
BOOL ret;
|
|
||||||
|
|
||||||
TRACE("(%p, %p, %p)\n", process->handle, cb, user);
|
|
||||||
macho_info.flags = MACHO_INFO_DEBUG_HEADER | MACHO_INFO_NAME;
|
|
||||||
ret = macho_enum_modules_internal(process, macho_info.module_name, cb, user);
|
|
||||||
HeapFree(GetProcessHeap(), 0, (char*)macho_info.module_name);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct macho_load
|
|
||||||
{
|
|
||||||
struct process* pcs;
|
|
||||||
struct macho_info macho_info;
|
|
||||||
const WCHAR* name;
|
|
||||||
BOOL ret;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* macho_load_cb
|
|
||||||
*
|
|
||||||
* Callback for macho_load_module, used to walk the list of loaded
|
|
||||||
* modules.
|
|
||||||
*/
|
|
||||||
static BOOL macho_load_cb(const WCHAR* name, unsigned long addr, void* user)
|
|
||||||
{
|
|
||||||
struct macho_load* ml = user;
|
|
||||||
const WCHAR* p;
|
|
||||||
|
|
||||||
TRACE("(%s, 0x%08lx, %p)\n", debugstr_w(name), addr, user);
|
|
||||||
|
|
||||||
/* memcmp is needed for matches when bufstr contains also version information
|
|
||||||
* ml->name: libc.so, name: libc.so.6.0
|
|
||||||
*/
|
|
||||||
p = file_name(name);
|
|
||||||
if (!memcmp(p, ml->name, lstrlenW(ml->name) * sizeof(WCHAR)))
|
|
||||||
{
|
|
||||||
ml->ret = macho_search_and_load_file(ml->pcs, name, addr, &ml->macho_info);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************
|
|
||||||
* macho_load_module
|
|
||||||
*
|
|
||||||
* Loads a Mach-O module and stores it in process' module list.
|
|
||||||
* Also, find module real name and load address from
|
|
||||||
* the real loaded modules list in pcs address space.
|
|
||||||
*/
|
|
||||||
struct module* macho_load_module(struct process* pcs, const WCHAR* name, unsigned long addr)
|
|
||||||
{
|
|
||||||
struct macho_load ml;
|
|
||||||
|
|
||||||
TRACE("(%p/%p, %s, 0x%08lx)\n", pcs, pcs->handle, debugstr_w(name), addr);
|
|
||||||
|
|
||||||
ml.macho_info.flags = MACHO_INFO_MODULE;
|
|
||||||
ml.ret = FALSE;
|
|
||||||
|
|
||||||
if (pcs->dbg_hdr_addr) /* we're debugging a live target */
|
|
||||||
{
|
|
||||||
ml.pcs = pcs;
|
|
||||||
/* do only the lookup from the filename, not the path (as we lookup module
|
|
||||||
* name in the process' loaded module list)
|
|
||||||
*/
|
|
||||||
ml.name = file_name(name);
|
|
||||||
ml.ret = FALSE;
|
|
||||||
|
|
||||||
if (!macho_enum_modules_internal(pcs, NULL, macho_load_cb, &ml))
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else if (addr)
|
|
||||||
{
|
|
||||||
ml.name = name;
|
|
||||||
ml.ret = macho_search_and_load_file(pcs, ml.name, addr, &ml.macho_info);
|
|
||||||
}
|
|
||||||
if (!ml.ret) return NULL;
|
|
||||||
assert(ml.macho_info.module);
|
|
||||||
return ml.macho_info.module;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* HAVE_MACH_O_LOADER_H */
|
#else /* HAVE_MACH_O_LOADER_H */
|
||||||
|
|
||||||
BOOL macho_synchronize_module_list(struct process* pcs)
|
BOOL macho_synchronize_module_list(struct process* pcs)
|
||||||
|
|
Loading…
Reference in New Issue