dbghelp: Expose some internal information about modules to winedbg.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
This commit is contained in:
parent
416d29e26c
commit
c50e02ec9c
10 changed files with 131 additions and 61 deletions
|
@ -67,6 +67,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
|||
|
||||
unsigned dbghelp_options = SYMOPT_UNDNAME;
|
||||
BOOL dbghelp_opt_native = FALSE;
|
||||
BOOL dbghelp_opt_extension_api = FALSE;
|
||||
BOOL dbghelp_opt_real_path = FALSE;
|
||||
BOOL dbghelp_opt_source_actual_path = FALSE;
|
||||
SYSTEM_INFO sysinfo;
|
||||
|
@ -612,6 +613,10 @@ BOOL WINAPI SymSetExtendedOption(IMAGEHLP_EXTENDED_OPTIONS option, BOOL value)
|
|||
old = dbghelp_opt_native;
|
||||
dbghelp_opt_native = value;
|
||||
break;
|
||||
case SYMOPT_EX_WINE_EXTENSION_API:
|
||||
old = dbghelp_opt_extension_api;
|
||||
dbghelp_opt_extension_api = value;
|
||||
break;
|
||||
case SYMOPT_EX_WINE_MODULE_REAL_PATH:
|
||||
old = dbghelp_opt_real_path;
|
||||
dbghelp_opt_real_path = value;
|
||||
|
@ -637,6 +642,8 @@ BOOL WINAPI SymGetExtendedOption(IMAGEHLP_EXTENDED_OPTIONS option)
|
|||
{
|
||||
case SYMOPT_EX_WINE_NATIVE_MODULES:
|
||||
return dbghelp_opt_native;
|
||||
case SYMOPT_EX_WINE_EXTENSION_API:
|
||||
return dbghelp_opt_extension_api;
|
||||
case SYMOPT_EX_WINE_MODULE_REAL_PATH:
|
||||
return dbghelp_opt_real_path;
|
||||
case SYMOPT_EX_WINE_SOURCE_ACTUAL_PATH:
|
||||
|
|
|
@ -215,3 +215,6 @@
|
|||
#@ stub sym
|
||||
#@ stub symsrv
|
||||
#@ stub vc7fpo
|
||||
|
||||
# wine extensions
|
||||
@ stdcall wine_get_module_information(long int64 ptr long)
|
||||
|
|
|
@ -112,6 +112,7 @@ void* hash_table_iter_up(struct hash_table_iter* hti);
|
|||
|
||||
extern unsigned dbghelp_options;
|
||||
extern BOOL dbghelp_opt_native;
|
||||
extern BOOL dbghelp_opt_extension_api;
|
||||
extern BOOL dbghelp_opt_real_path;
|
||||
extern BOOL dbghelp_opt_source_actual_path;
|
||||
extern SYSTEM_INFO sysinfo;
|
||||
|
@ -396,13 +397,6 @@ struct symt_udt
|
|||
struct vector vchildren;
|
||||
};
|
||||
|
||||
enum module_type
|
||||
{
|
||||
DMT_ELF, /* a real ELF shared module */
|
||||
DMT_PE, /* a native or builtin PE module */
|
||||
DMT_MACHO, /* a real Mach-O shared module */
|
||||
};
|
||||
|
||||
struct process;
|
||||
struct module;
|
||||
|
||||
|
@ -445,7 +439,7 @@ struct module
|
|||
IMAGEHLP_MODULEW64 module;
|
||||
WCHAR modulename[64]; /* used for enumeration */
|
||||
struct module* next;
|
||||
enum module_type type : 16;
|
||||
enum dhext_module_type type : 16;
|
||||
unsigned short is_virtual : 1;
|
||||
struct cpu* cpu;
|
||||
DWORD64 reloc_delta;
|
||||
|
@ -453,6 +447,7 @@ struct module
|
|||
|
||||
/* specific information for debug types */
|
||||
struct module_format* format_info[DFI_LAST];
|
||||
unsigned debug_format_bitmask;
|
||||
|
||||
/* memory allocation pool */
|
||||
struct pool pool;
|
||||
|
@ -742,7 +737,7 @@ extern struct module*
|
|||
extern BOOL module_get_debug(struct module_pair*);
|
||||
extern struct module*
|
||||
module_new(struct process* pcs, const WCHAR* name,
|
||||
enum module_type type, BOOL virtual,
|
||||
enum dhext_module_type type, BOOL virtual,
|
||||
DWORD64 addr, DWORD64 size,
|
||||
ULONG_PTR stamp, ULONG_PTR checksum, WORD machine);
|
||||
extern struct module*
|
||||
|
|
|
@ -2892,8 +2892,8 @@ static BOOL dwarf2_parse_compilation_unit_head(dwarf2_parse_context_t* ctx,
|
|||
TRACE("- word_size: %u\n", ctx->head.word_size);
|
||||
TRACE("- offset_size: %u\n", ctx->head.offset_size);
|
||||
|
||||
if (ctx->head.version >= 2)
|
||||
ctx->module_ctx->cu_versions |= 1 << (ctx->head.version - 2);
|
||||
if (ctx->head.version >= 2 && ctx->head.version <= 5)
|
||||
ctx->module_ctx->cu_versions |= DHEXT_FORMAT_DWARF2 << (ctx->head.version - 2);
|
||||
if (max_supported_dwarf_version == 0)
|
||||
{
|
||||
char* env = getenv("DBGHELP_DWARF_VERSION");
|
||||
|
@ -4259,17 +4259,16 @@ BOOL dwarf2_parse(struct module* module, ULONG_PTR load_offset,
|
|||
module_ctx.dwz = dwarf2_load_dwz(fmap, module);
|
||||
dwarf2_load_CU_module(&module_ctx, module, section, load_offset, thunks, FALSE);
|
||||
|
||||
dwarf2_modfmt->module->module.SymType = SymDia;
|
||||
/* hide dwarf versions in CVSig
|
||||
* bits 24-31 will be set according to found dwarf version
|
||||
* different CU can have different dwarf version, so use a bit per version (version 2 => b24)
|
||||
*/
|
||||
dwarf2_modfmt->module->module.CVSig = 'D' | ('W' << 8) | ('F' << 16) | ((module_ctx.cu_versions & 0xFF) << 24);
|
||||
/* FIXME: we could have a finer grain here */
|
||||
dwarf2_modfmt->module->module.GlobalSymbols = TRUE;
|
||||
dwarf2_modfmt->module->module.TypeInfo = TRUE;
|
||||
dwarf2_modfmt->module->module.SourceIndexed = TRUE;
|
||||
dwarf2_modfmt->module->module.Publics = TRUE;
|
||||
if (module_ctx.cu_versions)
|
||||
{
|
||||
dwarf2_modfmt->module->module.SymType = SymDia;
|
||||
module->debug_format_bitmask |= module_ctx.cu_versions;
|
||||
/* FIXME: we could have a finer grain here */
|
||||
dwarf2_modfmt->module->module.GlobalSymbols = TRUE;
|
||||
dwarf2_modfmt->module->module.TypeInfo = TRUE;
|
||||
dwarf2_modfmt->module->module.SourceIndexed = TRUE;
|
||||
dwarf2_modfmt->module->module.Publics = TRUE;
|
||||
}
|
||||
|
||||
dwarf2_unload_CU_module(&module_ctx);
|
||||
leave:
|
||||
|
|
|
@ -102,7 +102,7 @@ struct macho_section32
|
|||
*/
|
||||
struct image_file_map
|
||||
{
|
||||
enum module_type modtype;
|
||||
enum dhext_module_type modtype;
|
||||
const struct image_file_map_ops *ops;
|
||||
unsigned addr_size; /* either 16 (not used), 32 or 64 */
|
||||
struct image_file_map* alternate; /* another file linked to this one */
|
||||
|
|
|
@ -162,7 +162,7 @@ WCHAR *get_wine_loader_name(struct process *pcs)
|
|||
return altname;
|
||||
}
|
||||
|
||||
static const char* get_module_type(enum module_type type, BOOL virtual)
|
||||
static const char* get_module_type(enum dhext_module_type type, BOOL virtual)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
@ -177,7 +177,7 @@ static const char* get_module_type(enum module_type type, BOOL virtual)
|
|||
* Creates and links a new module to a process
|
||||
*/
|
||||
struct module* module_new(struct process* pcs, const WCHAR* name,
|
||||
enum module_type type, BOOL virtual,
|
||||
enum dhext_module_type type, BOOL virtual,
|
||||
DWORD64 mod_addr, DWORD64 size,
|
||||
ULONG_PTR stamp, ULONG_PTR checksum, WORD machine)
|
||||
{
|
||||
|
@ -238,6 +238,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
|
|||
module->cpu = cpu_find(machine);
|
||||
if (!module->cpu)
|
||||
module->cpu = dbghelp_current_cpu;
|
||||
module->debug_format_bitmask = 0;
|
||||
|
||||
vector_init(&module->vsymt, sizeof(struct symt*), 128);
|
||||
vector_init(&module->vcustom_symt, sizeof(struct symt*), 16);
|
||||
|
@ -1653,3 +1654,35 @@ const struct loader_ops empty_loader_ops =
|
|||
empty_enum_modules,
|
||||
native_fetch_file_info,
|
||||
};
|
||||
|
||||
BOOL WINAPI wine_get_module_information(HANDLE proc, DWORD64 base, struct dhext_module_information* wmi, unsigned len)
|
||||
{
|
||||
struct process* pcs;
|
||||
struct module* module;
|
||||
struct dhext_module_information dhmi;
|
||||
|
||||
/* could be interpreted as a WinDbg extension */
|
||||
if (!dbghelp_opt_extension_api)
|
||||
{
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TRACE("(%p %I64x %p %u\n", proc, base, wmi, len);
|
||||
|
||||
if (!(pcs = process_find_by_handle(proc))) return FALSE;
|
||||
if (len > sizeof(*wmi)) return FALSE;
|
||||
|
||||
module = module_find_by_addr(pcs, base);
|
||||
if (!module) return FALSE;
|
||||
|
||||
dhmi.type = module->type;
|
||||
dhmi.debug_format_bitmask = module->debug_format_bitmask;
|
||||
if ((module = module_get_container(pcs, module)))
|
||||
{
|
||||
dhmi.debug_format_bitmask |= module->debug_format_bitmask;
|
||||
}
|
||||
memcpy(wmi, &dhmi, len);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -1664,7 +1664,7 @@ BOOL stabs_parse(struct module* module, ULONG_PTR load_offset,
|
|||
stab_ptr->n_type, (ULONG_PTR)n_value, debugstr_a(strs + stab_ptr->n_strx));
|
||||
}
|
||||
module->module.SymType = SymDia;
|
||||
module->module.CVSig = 'S' | ('T' << 8) | ('A' << 16) | ('B' << 24);
|
||||
module->debug_format_bitmask |= DHEXT_FORMAT_STABS;
|
||||
/* FIXME: we could have a finer grain here */
|
||||
module->module.LineNumbers = TRUE;
|
||||
module->module.GlobalSymbols = TRUE;
|
||||
|
|
|
@ -1098,6 +1098,8 @@ typedef enum
|
|||
#ifdef __WINESRC__
|
||||
/* Include ELF/Mach-O modules in module operations */
|
||||
SYMOPT_EX_WINE_NATIVE_MODULES = 1000,
|
||||
/* Enable Wine's extension APIs */
|
||||
SYMOPT_EX_WINE_EXTENSION_API,
|
||||
/* Return the Unix actual path of loaded module */
|
||||
SYMOPT_EX_WINE_MODULE_REAL_PATH,
|
||||
/* Return the raw source file path from debug info (not always mapped to DOS) */
|
||||
|
@ -1240,6 +1242,37 @@ BOOL IMAGEAPI SymUnloadModule(HANDLE, DWORD);
|
|||
|
||||
#endif
|
||||
|
||||
#ifdef __WINESRC__
|
||||
|
||||
/* Wine extensions to dbghelp */
|
||||
enum dhext_module_type
|
||||
{
|
||||
DMT_UNKNOWN, /* for lookup, not actually used for a module */
|
||||
DMT_ELF, /* a real ELF shared module */
|
||||
DMT_MACHO, /* a real Mach-O shared module */
|
||||
DMT_PE, /* a native or builtin PE module */
|
||||
};
|
||||
|
||||
/* only reporting the formats not exposed in regular IMAGHELP_MODULE_INFO */
|
||||
enum dhext_debug_format
|
||||
{
|
||||
DHEXT_FORMAT_DWARF2 = 0x0001,
|
||||
DHEXT_FORMAT_DWARF3 = 0x0002,
|
||||
DHEXT_FORMAT_DWARF4 = 0x0004,
|
||||
DHEXT_FORMAT_DWARF5 = 0x0008,
|
||||
DHEXT_FORMAT_STABS = 0x0010,
|
||||
};
|
||||
|
||||
struct dhext_module_information
|
||||
{
|
||||
enum dhext_module_type type;
|
||||
unsigned debug_format_bitmask;
|
||||
};
|
||||
|
||||
extern BOOL WINAPI wine_get_module_information(HANDLE, DWORD64 base, struct dhext_module_information*, unsigned len);
|
||||
|
||||
#endif /* __WINESRC__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
|
|
@ -116,9 +116,23 @@ void info_help(void)
|
|||
while (infotext[i]) dbg_printf("%s\n", infotext[i++]);
|
||||
}
|
||||
|
||||
static const char* get_symtype_str(const IMAGEHLP_MODULE64* mi)
|
||||
struct info_module
|
||||
{
|
||||
switch (mi->SymType)
|
||||
IMAGEHLP_MODULEW64 mi;
|
||||
struct dhext_module_information ext_module_info;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct info_modules
|
||||
{
|
||||
struct info_module *modules;
|
||||
unsigned num_alloc;
|
||||
unsigned num_used;
|
||||
};
|
||||
|
||||
static const char* get_symtype_str(const struct info_module* im)
|
||||
{
|
||||
switch (im->mi.SymType)
|
||||
{
|
||||
default:
|
||||
case SymNone: return "--none--";
|
||||
|
@ -129,43 +143,26 @@ static const char* get_symtype_str(const IMAGEHLP_MODULE64* mi)
|
|||
case SymDeferred: return "Deferred";
|
||||
case SymSym: return "Sym";
|
||||
case SymDia:
|
||||
switch (mi->CVSig)
|
||||
if (im->ext_module_info.debug_format_bitmask)
|
||||
{
|
||||
case 'S' | ('T' << 8) | ('A' << 16) | ('B' << 24):
|
||||
return "Stabs";
|
||||
case 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24):
|
||||
/* previous versions of dbghelp used to report this... */
|
||||
return "Dwarf";
|
||||
default:
|
||||
if ((mi->CVSig & 0x00FFFFFF) == ('D' | ('W' << 8) | ('F' << 16)))
|
||||
static char tmp[64];
|
||||
tmp[0] = '\0';
|
||||
if (im->ext_module_info.debug_format_bitmask & DHEXT_FORMAT_STABS) strcpy(tmp, "stabs");
|
||||
if (im->ext_module_info.debug_format_bitmask & (DHEXT_FORMAT_DWARF2 | DHEXT_FORMAT_DWARF3 | DHEXT_FORMAT_DWARF4 | DHEXT_FORMAT_DWARF5))
|
||||
{
|
||||
static char tmp[64];
|
||||
DWORD versbit = mi->CVSig >> 24;
|
||||
strcpy(tmp, "Dwarf");
|
||||
if (versbit & 1) strcat(tmp, "-2");
|
||||
if (versbit & 2) strcat(tmp, "-3");
|
||||
if (versbit & 4) strcat(tmp, "-4");
|
||||
if (versbit & 8) strcat(tmp, "-5");
|
||||
return tmp;
|
||||
if (tmp[0]) strcat(tmp, ", ");
|
||||
strcat(tmp, "Dwarf");
|
||||
if (im->ext_module_info.debug_format_bitmask & DHEXT_FORMAT_DWARF2) strcat(tmp, "-2");
|
||||
if (im->ext_module_info.debug_format_bitmask & DHEXT_FORMAT_DWARF3) strcat(tmp, "-3");
|
||||
if (im->ext_module_info.debug_format_bitmask & DHEXT_FORMAT_DWARF4) strcat(tmp, "-4");
|
||||
if (im->ext_module_info.debug_format_bitmask & DHEXT_FORMAT_DWARF5) strcat(tmp, "-5");
|
||||
}
|
||||
return "DIA";
|
||||
return tmp;
|
||||
}
|
||||
return "DIA";
|
||||
}
|
||||
}
|
||||
|
||||
struct info_module
|
||||
{
|
||||
IMAGEHLP_MODULE64 mi;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct info_modules
|
||||
{
|
||||
struct info_module *modules;
|
||||
unsigned num_alloc;
|
||||
unsigned num_used;
|
||||
};
|
||||
|
||||
static const char* get_machine_str(DWORD machine)
|
||||
{
|
||||
static char tmp[32];
|
||||
|
@ -187,12 +184,12 @@ static void module_print_info(const struct info_module *module, BOOL is_embedded
|
|||
module->mi.BaseOfImage,
|
||||
module->mi.BaseOfImage + module->mi.ImageSize,
|
||||
get_machine_str(module->mi.MachineType),
|
||||
is_embedded ? "\\" : get_symtype_str(&module->mi), module->name);
|
||||
is_embedded ? "\\" : get_symtype_str(module), module->name);
|
||||
else
|
||||
dbg_printf("%*.*I64x-%*.*I64x\t%-16s%s\n",
|
||||
ADDRWIDTH, ADDRWIDTH, module->mi.BaseOfImage,
|
||||
ADDRWIDTH, ADDRWIDTH, module->mi.BaseOfImage + module->mi.ImageSize,
|
||||
is_embedded ? "\\" : get_symtype_str(&module->mi), module->name);
|
||||
is_embedded ? "\\" : get_symtype_str(module), module->name);
|
||||
}
|
||||
|
||||
static int __cdecl module_compare(const void* p1, const void* p2)
|
||||
|
@ -226,7 +223,9 @@ static BOOL CALLBACK info_mod_cb(PCSTR mod_name, DWORD64 base, PVOID ctx)
|
|||
im->modules = new;
|
||||
}
|
||||
im->modules[im->num_used].mi.SizeOfStruct = sizeof(im->modules[im->num_used].mi);
|
||||
if (SymGetModuleInfo64(dbg_curr_process->handle, base, &im->modules[im->num_used].mi))
|
||||
if (SymGetModuleInfoW64(dbg_curr_process->handle, base, &im->modules[im->num_used].mi) &&
|
||||
wine_get_module_information(dbg_curr_process->handle, base, &im->modules[im->num_used].ext_module_info,
|
||||
sizeof(im->modules[im->num_used].ext_module_info)))
|
||||
{
|
||||
const int dst_len = sizeof(im->modules[im->num_used].name);
|
||||
lstrcpynA(im->modules[im->num_used].name, mod_name, dst_len - 1);
|
||||
|
|
|
@ -723,6 +723,7 @@ int main(int argc, char** argv)
|
|||
SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS | SYMOPT_AUTO_PUBLICS |
|
||||
SYMOPT_INCLUDE_32BIT_MODULES);
|
||||
|
||||
SymSetExtendedOption(SYMOPT_EX_WINE_EXTENSION_API, TRUE);
|
||||
SymSetExtendedOption(SYMOPT_EX_WINE_SOURCE_ACTUAL_PATH, TRUE);
|
||||
|
||||
if (argc && !strcmp(argv[0], "--auto"))
|
||||
|
|
Loading…
Add table
Reference in a new issue