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;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* 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
|
||||
{
|
||||
enum_modules_cb cb;
|
||||
|
@ -1720,6 +1662,64 @@ BOOL elf_synchronize_module_list(struct process* pcs)
|
|||
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__ */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* get_dyld_image_info_address
|
||||
*/
|
||||
|
@ -1729,6 +1728,96 @@ BOOL macho_synchronize_module_list(struct process* pcs)
|
|||
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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* 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 */
|
||||
|
||||
BOOL macho_synchronize_module_list(struct process* pcs)
|
||||
|
|
Loading…
Reference in New Issue