dbghelp: Create new infrastructure to hold specific information for multiple file/debug formats in a single module, and use it to store dwarf2 stuff.
This commit is contained in:
parent
3e6920d7b8
commit
73f79e7fad
|
@ -313,6 +313,30 @@ enum module_type
|
||||||
};
|
};
|
||||||
|
|
||||||
struct process;
|
struct process;
|
||||||
|
struct module;
|
||||||
|
|
||||||
|
/* a module can be made of several debug information formats, so we have to
|
||||||
|
* support them all
|
||||||
|
*/
|
||||||
|
enum format_info
|
||||||
|
{
|
||||||
|
DFI_DWARF,
|
||||||
|
DFI_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
struct module_format
|
||||||
|
{
|
||||||
|
struct module* module;
|
||||||
|
void (*remove)(struct process* pcs, struct module_format* modfmt);
|
||||||
|
void (*loc_compute)(struct process* pcs,
|
||||||
|
const struct module_format* modfmt,
|
||||||
|
const struct symt_function* func,
|
||||||
|
struct location* loc);
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct dwarf2_module_info_s* dwarf2_info;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
struct module
|
struct module
|
||||||
{
|
{
|
||||||
|
@ -326,8 +350,8 @@ struct module
|
||||||
/* specific information for debug types */
|
/* specific information for debug types */
|
||||||
struct elf_module_info* elf_info;
|
struct elf_module_info* elf_info;
|
||||||
struct pe_module_info* pe_info;
|
struct pe_module_info* pe_info;
|
||||||
struct dwarf2_module_info_s*dwarf2_info;
|
|
||||||
void (*module_remove)(struct process* pcs, struct module* module);
|
void (*module_remove)(struct process* pcs, struct module* module);
|
||||||
|
struct module_format* format_info[DFI_LAST];
|
||||||
|
|
||||||
struct macho_module_info* macho_info;
|
struct macho_module_info* macho_info;
|
||||||
|
|
||||||
|
@ -342,10 +366,6 @@ struct module
|
||||||
unsigned sorttab_size;
|
unsigned sorttab_size;
|
||||||
struct symt_ht** addr_sorttab;
|
struct symt_ht** addr_sorttab;
|
||||||
struct hash_table ht_symbols;
|
struct hash_table ht_symbols;
|
||||||
void (*loc_compute)(struct process* pcs,
|
|
||||||
const struct module* module,
|
|
||||||
const struct symt_function* func,
|
|
||||||
struct location* loc);
|
|
||||||
|
|
||||||
/* types */
|
/* types */
|
||||||
struct hash_table ht_types;
|
struct hash_table ht_types;
|
||||||
|
|
|
@ -2212,7 +2212,7 @@ static BOOL dwarf2_parse_compilation_unit(const dwarf2_section_t* sections,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start,
|
static BOOL dwarf2_lookup_loclist(const struct module_format* modfmt, const BYTE* start,
|
||||||
unsigned long ip,
|
unsigned long ip,
|
||||||
dwarf2_traverse_context_t* lctx)
|
dwarf2_traverse_context_t* lctx)
|
||||||
{
|
{
|
||||||
|
@ -2220,7 +2220,7 @@ static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start
|
||||||
const BYTE* ptr = start;
|
const BYTE* ptr = start;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
|
|
||||||
while (ptr < module->dwarf2_info->debug_loc.address + module->dwarf2_info->debug_loc.size)
|
while (ptr < modfmt->u.dwarf2_info->debug_loc.address + modfmt->u.dwarf2_info->debug_loc.size)
|
||||||
{
|
{
|
||||||
beg = dwarf2_get_u4(ptr); ptr += 4;
|
beg = dwarf2_get_u4(ptr); ptr += 4;
|
||||||
end = dwarf2_get_u4(ptr); ptr += 4;
|
end = dwarf2_get_u4(ptr); ptr += 4;
|
||||||
|
@ -2241,7 +2241,7 @@ static BOOL dwarf2_lookup_loclist(const struct module* module, const BYTE* start
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum location_error loc_compute_frame(struct process* pcs,
|
static enum location_error loc_compute_frame(struct process* pcs,
|
||||||
const struct module* module,
|
const struct module_format* modfmt,
|
||||||
const struct symt_function* func,
|
const struct symt_function* func,
|
||||||
DWORD ip, struct location* frame)
|
DWORD ip, struct location* frame)
|
||||||
{
|
{
|
||||||
|
@ -2267,8 +2267,8 @@ static enum location_error loc_compute_frame(struct process* pcs,
|
||||||
break;
|
break;
|
||||||
case loc_dwarf2_location_list:
|
case loc_dwarf2_location_list:
|
||||||
WARN("Searching loclist for %s\n", func->hash_elt.name);
|
WARN("Searching loclist for %s\n", func->hash_elt.name);
|
||||||
if (!dwarf2_lookup_loclist(module,
|
if (!dwarf2_lookup_loclist(modfmt,
|
||||||
module->dwarf2_info->debug_loc.address + pframe->offset,
|
modfmt->u.dwarf2_info->debug_loc.address + pframe->offset,
|
||||||
ip, &lctx))
|
ip, &lctx))
|
||||||
return loc_err_out_of_scope;
|
return loc_err_out_of_scope;
|
||||||
if ((err = compute_location(&lctx, frame, pcs->handle, NULL)) < 0) return err;
|
if ((err = compute_location(&lctx, frame, pcs->handle, NULL)) < 0) return err;
|
||||||
|
@ -2290,7 +2290,7 @@ static enum location_error loc_compute_frame(struct process* pcs,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dwarf2_location_compute(struct process* pcs,
|
static void dwarf2_location_compute(struct process* pcs,
|
||||||
const struct module* module,
|
const struct module_format* modfmt,
|
||||||
const struct symt_function* func,
|
const struct symt_function* func,
|
||||||
struct location* loc)
|
struct location* loc)
|
||||||
{
|
{
|
||||||
|
@ -2309,14 +2309,14 @@ static void dwarf2_location_compute(struct process* pcs,
|
||||||
/* instruction pointer relative to compiland's start */
|
/* instruction pointer relative to compiland's start */
|
||||||
ip = pcs->ctx_frame.InstructionOffset - ((struct symt_compiland*)func->container)->address;
|
ip = pcs->ctx_frame.InstructionOffset - ((struct symt_compiland*)func->container)->address;
|
||||||
|
|
||||||
if ((err = loc_compute_frame(pcs, module, func, ip, &frame)) == 0)
|
if ((err = loc_compute_frame(pcs, modfmt, func, ip, &frame)) == 0)
|
||||||
{
|
{
|
||||||
switch (loc->kind)
|
switch (loc->kind)
|
||||||
{
|
{
|
||||||
case loc_dwarf2_location_list:
|
case loc_dwarf2_location_list:
|
||||||
/* Then, if the variable has a location list, find it !! */
|
/* Then, if the variable has a location list, find it !! */
|
||||||
if (dwarf2_lookup_loclist(module,
|
if (dwarf2_lookup_loclist(modfmt,
|
||||||
module->dwarf2_info->debug_loc.address + loc->offset,
|
modfmt->u.dwarf2_info->debug_loc.address + loc->offset,
|
||||||
ip, &lctx))
|
ip, &lctx))
|
||||||
goto do_compute;
|
goto do_compute;
|
||||||
err = loc_err_out_of_scope;
|
err = loc_err_out_of_scope;
|
||||||
|
@ -2351,6 +2351,12 @@ static void dwarf2_location_compute(struct process* pcs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dwarf2_module_remove(struct process* pcs, struct module_format* modfmt)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, modfmt->u.dwarf2_info);
|
||||||
|
HeapFree(GetProcessHeap(), 0, modfmt);
|
||||||
|
}
|
||||||
|
|
||||||
static inline BOOL dwarf2_init_section(dwarf2_section_t* section, struct image_file_map* fmap,
|
static inline BOOL dwarf2_init_section(dwarf2_section_t* section, struct image_file_map* fmap,
|
||||||
const char* sectname, struct image_section_map* ism)
|
const char* sectname, struct image_section_map* ism)
|
||||||
{
|
{
|
||||||
|
@ -2380,6 +2386,7 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
|
||||||
struct image_section_map debug_sect, debug_str_sect, debug_abbrev_sect,
|
struct image_section_map debug_sect, debug_str_sect, debug_abbrev_sect,
|
||||||
debug_line_sect, debug_loclist_sect;
|
debug_line_sect, debug_loclist_sect;
|
||||||
BOOL ret = TRUE;
|
BOOL ret = TRUE;
|
||||||
|
struct module_format* dwarf2_modfmt;
|
||||||
|
|
||||||
if (!dwarf2_init_section(§ion[section_debug], fmap, ".debug_info", &debug_sect))
|
if (!dwarf2_init_section(§ion[section_debug], fmap, ".debug_info", &debug_sect))
|
||||||
{
|
{
|
||||||
|
@ -2389,7 +2396,6 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
|
||||||
dwarf2_init_section(§ion[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect);
|
dwarf2_init_section(§ion[section_abbrev], fmap, ".debug_abbrev", &debug_abbrev_sect);
|
||||||
dwarf2_init_section(§ion[section_string], fmap, ".debug_str", &debug_str_sect);
|
dwarf2_init_section(§ion[section_string], fmap, ".debug_str", &debug_str_sect);
|
||||||
dwarf2_init_section(§ion[section_line], fmap, ".debug_line", &debug_line_sect);
|
dwarf2_init_section(§ion[section_line], fmap, ".debug_line", &debug_line_sect);
|
||||||
image_find_section(fmap, ".debug_loc", &debug_loclist_sect);
|
|
||||||
|
|
||||||
if (section[section_debug].address == IMAGE_NO_MAP ||
|
if (section[section_debug].address == IMAGE_NO_MAP ||
|
||||||
section[section_abbrev].address == IMAGE_NO_MAP ||
|
section[section_abbrev].address == IMAGE_NO_MAP ||
|
||||||
|
@ -2413,32 +2419,41 @@ BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
|
||||||
mod_ctx.start_data = mod_ctx.data = section[section_debug].address;
|
mod_ctx.start_data = mod_ctx.data = section[section_debug].address;
|
||||||
mod_ctx.end_data = mod_ctx.data + section[section_debug].size;
|
mod_ctx.end_data = mod_ctx.data + section[section_debug].size;
|
||||||
|
|
||||||
module->loc_compute = dwarf2_location_compute;
|
|
||||||
|
|
||||||
|
dwarf2_modfmt = HeapAlloc(GetProcessHeap(), 0, sizeof(*dwarf2_modfmt));
|
||||||
|
if (!dwarf2_modfmt) return FALSE;
|
||||||
|
dwarf2_modfmt->module = module;
|
||||||
|
dwarf2_modfmt->remove = dwarf2_module_remove;
|
||||||
|
dwarf2_modfmt->loc_compute = dwarf2_location_compute;
|
||||||
|
dwarf2_modfmt->u.dwarf2_info = NULL;
|
||||||
|
dwarf2_modfmt->module->format_info[DFI_DWARF] = dwarf2_modfmt;
|
||||||
|
|
||||||
|
image_find_section(fmap, ".debug_loc", &debug_loclist_sect);
|
||||||
if (image_get_map_size(&debug_loclist_sect))
|
if (image_get_map_size(&debug_loclist_sect))
|
||||||
{
|
{
|
||||||
/* initialize the dwarf2 specific info block for this module.
|
/* initialize the dwarf2 specific info block for this module.
|
||||||
* As we'll need later the .debug_loc section content, we won't unmap this
|
* As we'll need later the .debug_loc section content, we won't unmap this
|
||||||
* section upon existing this function
|
* section upon existing this function
|
||||||
*/
|
*/
|
||||||
module->dwarf2_info = HeapAlloc(GetProcessHeap(), 0, sizeof(*module->dwarf2_info));
|
dwarf2_modfmt->u.dwarf2_info = HeapAlloc(GetProcessHeap(), 0,
|
||||||
if (!module->dwarf2_info) return FALSE;
|
sizeof(*dwarf2_modfmt->u.dwarf2_info));
|
||||||
module->dwarf2_info->debug_loc.address = (const BYTE*)image_map_section(&debug_loclist_sect);
|
if (!dwarf2_modfmt->u.dwarf2_info) goto leave;
|
||||||
module->dwarf2_info->debug_loc.size = image_get_map_size(&debug_loclist_sect);
|
dwarf2_modfmt->u.dwarf2_info->debug_loc.address = (const BYTE*)image_map_section(&debug_loclist_sect);
|
||||||
|
dwarf2_modfmt->u.dwarf2_info->debug_loc.size = image_get_map_size(&debug_loclist_sect);
|
||||||
}
|
}
|
||||||
else image_unmap_section(&debug_loclist_sect);
|
else image_unmap_section(&debug_loclist_sect);
|
||||||
|
|
||||||
while (mod_ctx.data < mod_ctx.end_data)
|
while (mod_ctx.data < mod_ctx.end_data)
|
||||||
{
|
{
|
||||||
dwarf2_parse_compilation_unit(section, module, thunks, &mod_ctx, load_offset);
|
dwarf2_parse_compilation_unit(section, dwarf2_modfmt->module, thunks, &mod_ctx, load_offset);
|
||||||
}
|
}
|
||||||
module->module.SymType = SymDia;
|
dwarf2_modfmt->module->module.SymType = SymDia;
|
||||||
module->module.CVSig = 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24);
|
dwarf2_modfmt->module->module.CVSig = 'D' | ('W' << 8) | ('A' << 16) | ('R' << 24);
|
||||||
/* FIXME: we could have a finer grain here */
|
/* FIXME: we could have a finer grain here */
|
||||||
module->module.GlobalSymbols = TRUE;
|
dwarf2_modfmt->module->module.GlobalSymbols = TRUE;
|
||||||
module->module.TypeInfo = TRUE;
|
dwarf2_modfmt->module->module.TypeInfo = TRUE;
|
||||||
module->module.SourceIndexed = TRUE;
|
dwarf2_modfmt->module->module.SourceIndexed = TRUE;
|
||||||
module->module.Publics = TRUE;
|
dwarf2_modfmt->module->module.Publics = TRUE;
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
image_unmap_section(&debug_sect);
|
image_unmap_section(&debug_sect);
|
||||||
|
|
|
@ -126,6 +126,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
|
||||||
unsigned long stamp, unsigned long checksum)
|
unsigned long stamp, unsigned long checksum)
|
||||||
{
|
{
|
||||||
struct module* module;
|
struct module* module;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO);
|
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))))
|
||||||
|
@ -168,7 +169,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
|
||||||
|
|
||||||
module->type = type;
|
module->type = type;
|
||||||
module->is_virtual = virtual ? TRUE : FALSE;
|
module->is_virtual = virtual ? TRUE : FALSE;
|
||||||
module->module_remove = NULL;
|
for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL;
|
||||||
module->sortlist_valid = FALSE;
|
module->sortlist_valid = FALSE;
|
||||||
module->sorttab_size = 0;
|
module->sorttab_size = 0;
|
||||||
module->addr_sorttab = NULL;
|
module->addr_sorttab = NULL;
|
||||||
|
@ -622,16 +623,22 @@ DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
|
||||||
*/
|
*/
|
||||||
BOOL module_remove(struct process* pcs, struct module* module)
|
BOOL module_remove(struct process* pcs, struct module* module)
|
||||||
{
|
{
|
||||||
|
struct module_format*modfmt;
|
||||||
struct module** p;
|
struct module** p;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module);
|
TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module);
|
||||||
|
|
||||||
if (module->module_remove) module->module_remove(pcs, module);
|
if (module->module_remove) module->module_remove(pcs, module);
|
||||||
|
for (i = 0; i < DFI_LAST; i++)
|
||||||
|
{
|
||||||
|
if ((modfmt = module->format_info[i]) && modfmt->remove)
|
||||||
|
modfmt->remove(pcs, module->format_info[i]);
|
||||||
|
}
|
||||||
hash_table_destroy(&module->ht_symbols);
|
hash_table_destroy(&module->ht_symbols);
|
||||||
hash_table_destroy(&module->ht_types);
|
hash_table_destroy(&module->ht_types);
|
||||||
HeapFree(GetProcessHeap(), 0, module->sources);
|
HeapFree(GetProcessHeap(), 0, module->sources);
|
||||||
HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
|
HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
|
||||||
HeapFree(GetProcessHeap(), 0, module->dwarf2_info);
|
|
||||||
pool_destroy(&module->pool);
|
pool_destroy(&module->pool);
|
||||||
/* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here
|
/* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here
|
||||||
* so do we
|
* so do we
|
||||||
|
|
|
@ -693,8 +693,20 @@ static void symt_fill_sym_info(struct module_pair* pair,
|
||||||
struct location loc = data->u.var;
|
struct location loc = data->u.var;
|
||||||
|
|
||||||
if (loc.kind >= loc_user)
|
if (loc.kind >= loc_user)
|
||||||
pair->effective->loc_compute(pair->pcs, pair->effective, func, &loc);
|
{
|
||||||
|
unsigned i;
|
||||||
|
struct module_format* modfmt;
|
||||||
|
|
||||||
|
for (i = 0; i < DFI_LAST; i++)
|
||||||
|
{
|
||||||
|
modfmt = pair->effective->format_info[i];
|
||||||
|
if (modfmt && modfmt->loc_compute)
|
||||||
|
{
|
||||||
|
modfmt->loc_compute(pair->pcs, modfmt, func, &loc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
switch (loc.kind)
|
switch (loc.kind)
|
||||||
{
|
{
|
||||||
case loc_error:
|
case loc_error:
|
||||||
|
|
Loading…
Reference in New Issue