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 \
elf_module.c \
image.c \
macho_module.c \
memory.c \
minidump.c \
module.c \

View file

@ -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)
{

View file

@ -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[];

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_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))
module = elf_load_module(pcs, wImageName, BaseOfDll);
/* 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))

View file

@ -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;

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)
{
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;
}