dbghelp: Add support for debugging Mach-O modules.

This commit is contained in:
Ken Thomases 2009-03-13 11:48:00 -05:00 committed by Alexandre Julliard
parent db37679b4e
commit d7466e0c4e
7 changed files with 1515 additions and 15 deletions

View File

@ -15,6 +15,7 @@ C_SRCS = \
dwarf.c \ dwarf.c \
elf_module.c \ elf_module.c \
image.c \ image.c \
macho_module.c \
memory.c \ memory.c \
minidump.c \ minidump.c \
module.c \ module.c \

View File

@ -232,7 +232,8 @@ static BOOL check_live_target(struct process* pcs)
{ {
if (!GetProcessId(pcs->handle)) return FALSE; if (!GetProcessId(pcs->handle)) return FALSE;
if (GetEnvironmentVariableA("DBGHELP_NOLIVE", NULL, 0)) 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; return TRUE;
} }
@ -327,6 +328,7 @@ BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeP
if (fInvadeProcess) if (fInvadeProcess)
EnumerateLoadedModules(hProcess, process_invade_cb, hProcess); EnumerateLoadedModules(hProcess, process_invade_cb, hProcess);
elf_synchronize_module_list(pcs); elf_synchronize_module_list(pcs);
macho_synchronize_module_list(pcs);
} }
else if (fInvadeProcess) else if (fInvadeProcess)
{ {

View File

@ -303,6 +303,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_MACHO, /* a real Mach-O shared module */
DMT_PDB, /* .PDB file */ DMT_PDB, /* .PDB file */
DMT_DBG, /* .DBG file */ DMT_DBG, /* .DBG file */
}; };
@ -322,6 +323,8 @@ struct module
struct elf_module_info* elf_info; struct elf_module_info* elf_info;
struct dwarf2_module_info_s*dwarf2_info; struct dwarf2_module_info_s*dwarf2_info;
struct macho_module_info* macho_info;
/* memory allocation pool */ /* memory allocation pool */
struct pool 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); typedef BOOL (*enum_modules_cb)(const WCHAR*, unsigned long addr, void* user);
/* elf_module.c */ /* 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_enum_modules(HANDLE hProc, enum_modules_cb, void*);
extern BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum); extern BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum);
struct elf_file_map; 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 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); 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 */ /* module.c */
extern const WCHAR S_ElfW[]; extern const WCHAR S_ElfW[];
extern const WCHAR S_WineLoaderW[]; extern const WCHAR S_WineLoaderW[];

1438
dlls/dbghelp/macho_module.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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_ELF: return virtual ? "Virtual ELF" : "ELF";
case DMT_PE: return virtual ? "Virtual PE" : "PE"; case DMT_PE: return virtual ? "Virtual PE" : "PE";
case DMT_MACHO: return virtual ? "Virtual Mach-O" : "Mach-O";
default: return "---"; default: return "---";
} }
} }
@ -125,7 +126,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
{ {
struct module* module; 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)))) if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module))))
return NULL; 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, ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
&idslW64); &idslW64);
break; break;
case DMT_MACHO:
ret = macho_load_debug_info(pair->effective, NULL);
break;
default: default:
ret = FALSE; ret = FALSE;
break; break;
@ -341,7 +345,8 @@ struct module* module_find_by_addr(const struct process* pcs, unsigned long addr
if (type == DMT_UNKNOWN) if (type == DMT_UNKNOWN)
{ {
if ((module = module_find_by_addr(pcs, addr, DMT_PE)) || 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; return module;
} }
else else
@ -376,7 +381,7 @@ static BOOL module_is_container_loaded(const struct process* pcs,
for (module = pcs->lmodules; module; module = module->next) 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 &&
base < module->module.BaseOfImage + module->module.ImageSize) base < module->module.BaseOfImage + module->module.ImageSize)
{ {
@ -416,8 +421,14 @@ enum module_type module_get_type_by_name(const WCHAR* name)
} while (len); } while (len);
/* check for terminating .so or .so.[digit] */ /* 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)) if (len > 3 && !memcmp(name + len - 3, S_DotSoW, 3))
#ifdef __APPLE__
return DMT_MACHO;
#else
return DMT_ELF; return DMT_ELF;
#endif
if (len > 4 && !strncmpiW(name + len - 4, S_DotPdbW, 4)) if (len > 4 && !strncmpiW(name + len - 4, S_DotPdbW, 4))
return DMT_PDB; 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)) if (len > 4 && !strncmpiW(name + len - 4, S_DotDbgW, 4))
return DMT_DBG; 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)) if (((len > 4 && name[len - 5] == '/') || len == 4) && !strcmpiW(name + len - 4, S_WineW))
{
#ifdef __APPLE__
return DMT_MACHO;
#else
return DMT_ELF; return DMT_ELF;
#endif
}
return DMT_PE; return DMT_PE;
} }
@ -513,8 +529,9 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
if (Flags & ~(SLMFLAG_VIRTUAL)) if (Flags & ~(SLMFLAG_VIRTUAL))
FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName)); 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); elf_synchronize_module_list(pcs);
macho_synchronize_module_list(pcs);
/* this is a Wine extension to the API just to redo the synchronisation */ /* this is a Wine extension to the API just to redo the synchronisation */
if (!wImageName && !hFile) return 0; if (!wImageName && !hFile) return 0;
@ -534,11 +551,22 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
if (!module) if (!module)
{ {
/* otherwise, try a regular PE 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 */ /* and finally an ELF or Mach-O module */
if (wImageName && (module_get_type_by_name(wImageName) == DMT_ELF)) switch (module_get_type_by_name(wImageName))
module = elf_load_module(pcs, wImageName, BaseOfDll); {
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) if (!module)
@ -709,7 +737,8 @@ BOOL WINAPI SymEnumerateModulesW64(HANDLE hProcess,
for (module = pcs->lmodules; module; module = module->next) 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; continue;
if (!EnumModulesCallback(module->module.ModuleName, if (!EnumModulesCallback(module->module.ModuleName,
module->module.BaseOfImage, UserContext)) module->module.BaseOfImage, UserContext))

View File

@ -522,6 +522,21 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user)
return FALSE; return FALSE;
} }
break; 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: case DMT_PDB:
{ {
struct pdb_lookup pdb_lookup; struct pdb_lookup pdb_lookup;

View File

@ -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) 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_containee(pair.pcs, pair.requested) &&
module_get_debug(&pair)) 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) 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)) find_name(pcs, module, Name, Symbol))
return TRUE; return TRUE;
} }