dbghelp: Add support for debugging Mach-O modules.
This commit is contained in:
parent
db37679b4e
commit
d7466e0c4e
|
@ -15,6 +15,7 @@ C_SRCS = \
|
|||
dwarf.c \
|
||||
elf_module.c \
|
||||
image.c \
|
||||
macho_module.c \
|
||||
memory.c \
|
||||
minidump.c \
|
||||
module.c \
|
||||
|
|
|
@ -232,7 +232,8 @@ static BOOL check_live_target(struct process* pcs)
|
|||
{
|
||||
if (!GetProcessId(pcs->handle)) return FALSE;
|
||||
if (GetEnvironmentVariableA("DBGHELP_NOLIVE", NULL, 0)) return FALSE;
|
||||
elf_read_wine_loader_dbg_info(pcs);
|
||||
if (!elf_read_wine_loader_dbg_info(pcs))
|
||||
macho_read_wine_loader_dbg_info(pcs);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -327,6 +328,7 @@ BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeP
|
|||
if (fInvadeProcess)
|
||||
EnumerateLoadedModules(hProcess, process_invade_cb, hProcess);
|
||||
elf_synchronize_module_list(pcs);
|
||||
macho_synchronize_module_list(pcs);
|
||||
}
|
||||
else if (fInvadeProcess)
|
||||
{
|
||||
|
|
|
@ -303,6 +303,7 @@ enum module_type
|
|||
DMT_UNKNOWN, /* for lookup, not actually used for a module */
|
||||
DMT_ELF, /* a real ELF shared module */
|
||||
DMT_PE, /* a native or builtin PE module */
|
||||
DMT_MACHO, /* a real Mach-O shared module */
|
||||
DMT_PDB, /* .PDB file */
|
||||
DMT_DBG, /* .DBG file */
|
||||
};
|
||||
|
@ -322,6 +323,8 @@ struct module
|
|||
struct elf_module_info* elf_info;
|
||||
struct dwarf2_module_info_s*dwarf2_info;
|
||||
|
||||
struct macho_module_info* macho_info;
|
||||
|
||||
/* memory allocation pool */
|
||||
struct pool pool;
|
||||
|
||||
|
@ -419,7 +422,7 @@ extern DWORD calc_crc32(int fd);
|
|||
typedef BOOL (*enum_modules_cb)(const WCHAR*, unsigned long addr, void* user);
|
||||
|
||||
/* elf_module.c */
|
||||
#define ELF_NO_MAP ((const void*)0xffffffff)
|
||||
#define ELF_NO_MAP ((const void*)-1)
|
||||
extern BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb, void*);
|
||||
extern BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum);
|
||||
struct elf_file_map;
|
||||
|
@ -432,6 +435,17 @@ struct elf_thunk_area;
|
|||
extern int elf_is_in_thunk_area(unsigned long addr, const struct elf_thunk_area* thunks);
|
||||
extern DWORD WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDRESS* addr);
|
||||
|
||||
/* macho_module.c */
|
||||
#define MACHO_NO_MAP ((const void*)-1)
|
||||
extern BOOL macho_enum_modules(HANDLE hProc, enum_modules_cb, void*);
|
||||
extern BOOL macho_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum);
|
||||
struct macho_file_map;
|
||||
extern BOOL macho_load_debug_info(struct module* module, struct macho_file_map* fmap);
|
||||
extern struct module*
|
||||
macho_load_module(struct process* pcs, const WCHAR* name, unsigned long);
|
||||
extern BOOL macho_read_wine_loader_dbg_info(struct process* pcs);
|
||||
extern BOOL macho_synchronize_module_list(struct process* pcs);
|
||||
|
||||
/* module.c */
|
||||
extern const WCHAR S_ElfW[];
|
||||
extern const WCHAR S_WineLoaderW[];
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -111,6 +111,7 @@ static const char* get_module_type(enum module_type type, BOOL virtual)
|
|||
{
|
||||
case DMT_ELF: return virtual ? "Virtual ELF" : "ELF";
|
||||
case DMT_PE: return virtual ? "Virtual PE" : "PE";
|
||||
case DMT_MACHO: return virtual ? "Virtual Mach-O" : "Mach-O";
|
||||
default: return "---";
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +126,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
|
|||
{
|
||||
struct module* module;
|
||||
|
||||
assert(type == DMT_ELF || type == DMT_PE);
|
||||
assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO);
|
||||
if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module))))
|
||||
return NULL;
|
||||
|
||||
|
@ -316,6 +317,9 @@ BOOL module_get_debug(struct module_pair* pair)
|
|||
ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
|
||||
&idslW64);
|
||||
break;
|
||||
case DMT_MACHO:
|
||||
ret = macho_load_debug_info(pair->effective, NULL);
|
||||
break;
|
||||
default:
|
||||
ret = FALSE;
|
||||
break;
|
||||
|
@ -341,7 +345,8 @@ struct module* module_find_by_addr(const struct process* pcs, unsigned long addr
|
|||
if (type == DMT_UNKNOWN)
|
||||
{
|
||||
if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
|
||||
(module = module_find_by_addr(pcs, addr, DMT_ELF)))
|
||||
(module = module_find_by_addr(pcs, addr, DMT_ELF)) ||
|
||||
(module = module_find_by_addr(pcs, addr, DMT_MACHO)))
|
||||
return module;
|
||||
}
|
||||
else
|
||||
|
@ -376,7 +381,7 @@ static BOOL module_is_container_loaded(const struct process* pcs,
|
|||
|
||||
for (module = pcs->lmodules; module; module = module->next)
|
||||
{
|
||||
if (module->type == DMT_ELF &&
|
||||
if ((module->type == DMT_ELF || module->type == DMT_MACHO) &&
|
||||
base >= module->module.BaseOfImage &&
|
||||
base < module->module.BaseOfImage + module->module.ImageSize)
|
||||
{
|
||||
|
@ -416,8 +421,14 @@ enum module_type module_get_type_by_name(const WCHAR* name)
|
|||
} while (len);
|
||||
|
||||
/* check for terminating .so or .so.[digit] */
|
||||
/* FIXME: Can't rely solely on extension; have to check magic or
|
||||
* stop using .so on Mac OS X. For now, base on platform. */
|
||||
if (len > 3 && !memcmp(name + len - 3, S_DotSoW, 3))
|
||||
#ifdef __APPLE__
|
||||
return DMT_MACHO;
|
||||
#else
|
||||
return DMT_ELF;
|
||||
#endif
|
||||
|
||||
if (len > 4 && !strncmpiW(name + len - 4, S_DotPdbW, 4))
|
||||
return DMT_PDB;
|
||||
|
@ -425,10 +436,15 @@ enum module_type module_get_type_by_name(const WCHAR* name)
|
|||
if (len > 4 && !strncmpiW(name + len - 4, S_DotDbgW, 4))
|
||||
return DMT_DBG;
|
||||
|
||||
/* wine is also an ELF module */
|
||||
/* wine is also a native module (Mach-O on Mac OS X, ELF elsewhere) */
|
||||
if (((len > 4 && name[len - 5] == '/') || len == 4) && !strcmpiW(name + len - 4, S_WineW))
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return DMT_MACHO;
|
||||
#else
|
||||
return DMT_ELF;
|
||||
|
||||
#endif
|
||||
}
|
||||
return DMT_PE;
|
||||
}
|
||||
|
||||
|
@ -513,8 +529,9 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
|
|||
if (Flags & ~(SLMFLAG_VIRTUAL))
|
||||
FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName));
|
||||
|
||||
/* force transparent ELF loading / unloading */
|
||||
/* force transparent ELF and Mach-O loading / unloading */
|
||||
elf_synchronize_module_list(pcs);
|
||||
macho_synchronize_module_list(pcs);
|
||||
|
||||
/* this is a Wine extension to the API just to redo the synchronisation */
|
||||
if (!wImageName && !hFile) return 0;
|
||||
|
@ -534,11 +551,22 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
|
|||
if (!module)
|
||||
{
|
||||
/* otherwise, try a regular PE module */
|
||||
if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)))
|
||||
if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)) &&
|
||||
wImageName)
|
||||
{
|
||||
/* and finally and ELF module */
|
||||
if (wImageName && (module_get_type_by_name(wImageName) == DMT_ELF))
|
||||
/* and finally an ELF or Mach-O module */
|
||||
switch (module_get_type_by_name(wImageName))
|
||||
{
|
||||
case DMT_ELF:
|
||||
module = elf_load_module(pcs, wImageName, BaseOfDll);
|
||||
break;
|
||||
case DMT_MACHO:
|
||||
module = macho_load_module(pcs, wImageName, BaseOfDll);
|
||||
break;
|
||||
default:
|
||||
/* Ignored */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!module)
|
||||
|
@ -709,7 +737,8 @@ BOOL WINAPI SymEnumerateModulesW64(HANDLE hProcess,
|
|||
|
||||
for (module = pcs->lmodules; module; module = module->next)
|
||||
{
|
||||
if (!(dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES) && module->type == DMT_ELF)
|
||||
if (!(dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES) &&
|
||||
(module->type == DMT_ELF || module->type == DMT_MACHO))
|
||||
continue;
|
||||
if (!EnumModulesCallback(module->module.ModuleName,
|
||||
module->module.BaseOfImage, UserContext))
|
||||
|
|
|
@ -522,6 +522,21 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user)
|
|||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case DMT_MACHO:
|
||||
if (macho_fetch_file_info(buffer, 0, &size, &checksum))
|
||||
{
|
||||
matched++;
|
||||
if (checksum == mf->dw1) matched++;
|
||||
else
|
||||
WARN("Found %s, but wrong checksums: %08x %08x\n",
|
||||
debugstr_w(buffer), checksum, mf->dw1);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Couldn't read %s\n", debugstr_w(buffer));
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case DMT_PDB:
|
||||
{
|
||||
struct pdb_lookup pdb_lookup;
|
||||
|
|
|
@ -1013,7 +1013,7 @@ static BOOL sym_enum(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
|
|||
{
|
||||
for (pair.requested = pair.pcs->lmodules; pair.requested; pair.requested = pair.requested->next)
|
||||
{
|
||||
if (pair.requested->type == DMT_ELF &&
|
||||
if ((pair.requested->type == DMT_ELF || pair.requested->type == DMT_MACHO) &&
|
||||
!module_get_containee(pair.pcs, pair.requested) &&
|
||||
module_get_debug(&pair))
|
||||
{
|
||||
|
@ -1340,7 +1340,8 @@ BOOL WINAPI SymFromName(HANDLE hProcess, PCSTR Name, PSYMBOL_INFO Symbol)
|
|||
{
|
||||
for (module = pcs->lmodules; module; module = module->next)
|
||||
{
|
||||
if (module->type == DMT_ELF && !module_get_containee(pcs, module) &&
|
||||
if ((module->type == DMT_ELF || module->type == DMT_MACHO) &&
|
||||
!module_get_containee(pcs, module) &&
|
||||
find_name(pcs, module, Name, Symbol))
|
||||
return TRUE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue