This serie mainly moves the handling of local variables described with DEFRANGE into the new reader. Fixing in the process a couple of bugs. Rest if mainly cleanup and helpers.
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/pdb.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-)
diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 84f94e32338..708bc1fece3 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -583,22 +583,16 @@ struct pdb_reader_linetab2_location static enum pdb_result pdb_find_matching_linetab2(struct CV_Line_t *lines, unsigned num_lines, DWORD64 delta, unsigned *index) { unsigned i; - for (i = 0; i + 1 < num_lines; i++) - { - unsigned j; - for (j = i + 1; j < num_lines; j++) - if (lines[j].offset != lines[i].offset) break; - if (j >= num_lines) break; - if (delta < lines[j].offset) - { - *index = i; - return R_PDB_SUCCESS; - } - } /* since the the address is inside the file_hdr, we assume then it's matched by last entry * (for which we don't have the next entry) */ - *index = num_lines - 1; + for (i = 0; i + 1 < num_lines; i++) + { + if (lines[i].offset == delta || + (lines[i].offset <= delta && delta < lines[i + 1].offset)) + break; + } + *index = i; return R_PDB_SUCCESS; }
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/symbol.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 5d376806c1a..8399b113ab3 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -715,6 +715,8 @@ static void symt_fill_sym_info(struct module_pair* pair, sym_info->ModBase = pair->requested->module.BaseOfImage; sym_info->Flags = 0; sym_info->Value = 0; + sym_info->Address = 0; + sym_info->Register = 0;
switch (sym->tag) { @@ -750,7 +752,6 @@ static void symt_fill_sym_info(struct module_pair* pair, case loc_register: sym_info->Flags |= SYMFLAG_REGISTER; sym_info->Register = loc.reg; - sym_info->Address = 0; break; case loc_regrel: sym_info->Flags |= SYMFLAG_REGREL; @@ -779,7 +780,6 @@ static void symt_fill_sym_info(struct module_pair* pair, /* fall through */ case loc_absolute: symt_get_address(sym, &sym_info->Address); - sym_info->Register = 0; break; default: FIXME("Shouldn't happen (kind=%d), debug reader backend is broken\n", data->u.var.kind); @@ -839,7 +839,6 @@ static void symt_fill_sym_info(struct module_pair* pair, break; default: symt_get_address(sym, &sym_info->Address); - sym_info->Register = 0; break; } sym_info->Scope = 0; /* FIXME */
From: Eric Pouech epouech@codeweavers.com
(making use of already set values by Dwarf backend).
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/symbol.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 8399b113ab3..65eb4fd3106 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -694,7 +694,7 @@ struct symt_custom* symt_new_custom(struct module* module, const char* name, }
/* expect sym_info->MaxNameLen to be set before being called */ -static void symt_fill_sym_info(struct module_pair* pair, +static BOOL symt_fill_sym_info(struct module_pair* pair, const struct symt_function* func, const struct symt* sym, SYMBOL_INFO* sym_info) { @@ -741,6 +741,7 @@ static void symt_fill_sym_info(struct module_pair* pair, MODULE_FORMAT_VTABLE_INDEX(loc_compute)))) { iter.modfmt->vtable->loc_compute(iter.modfmt, func, &loc); + if (loc.kind == loc_error && loc.reg == loc_err_out_of_scope) return FALSE; break; } } @@ -856,6 +857,7 @@ static void symt_fill_sym_info(struct module_pair* pair,
TRACE_(dbghelp_symt)("%p => %s %lu %I64x\n", sym, debugstr_a(sym_info->Name), sym_info->Size, sym_info->Address); + return TRUE; }
struct sym_enum @@ -872,7 +874,7 @@ struct sym_enum static BOOL send_symbol(const struct sym_enum* se, struct module_pair* pair, const struct symt_function* func, const struct symt* sym) { - symt_fill_sym_info(pair, func, sym, se->sym_info); + if (!symt_fill_sym_info(pair, func, sym, se->sym_info)) return FALSE; if (se->index && se->sym_info->Index != se->index) return FALSE; if (se->tag && se->sym_info->Tag != se->tag) return FALSE; if (se->addr && !(se->addr >= se->sym_info->Address && se->addr < se->sym_info->Address + se->sym_info->Size)) return FALSE;
From: Eric Pouech epouech@codeweavers.com
Fixing a couple of bugs in the process.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/msc.c | 16 ++++- dlls/dbghelp/pdb.c | 173 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 184 insertions(+), 5 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index f4a8426ffe8..6c8f9b3637d 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -2298,6 +2298,7 @@ static struct symt_compiland* codeview_new_compiland(const struct msc_debug_info }
static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, + unsigned stream_id, const BYTE* root, unsigned offset, unsigned size, const struct cv_module_snarf* cvmod, const char* objname) @@ -2699,7 +2700,15 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, */ if (!sym->local_v3.varflags.enreg_global && !sym->local_v3.varflags.enreg_static) { - length += codeview_transform_defrange(msc_dbg, curr_func, sym, &loc); + if (stream_id) + { + loc.kind = loc_user + 1 /* loc_cv_defrange for new PDB reader (see pdb.c) */; + loc.reg = stream_id; + loc.offset = (const BYTE*)sym - root; + length += codeview_defrange_length(sym); + } + else + length += codeview_transform_defrange(msc_dbg, curr_func, sym, &loc); symt_add_func_local(msc_dbg->module, curr_func, sym->local_v3.varflags.is_param ? DataIsParam : DataIsLocal, &loc, block, @@ -3904,7 +3913,8 @@ static BOOL pdb_process_internal(const struct process *pcs, { struct cv_module_snarf cvmod = {ipi_ok ? &ipi_ctp : NULL, (const void*)(modimage + sfile.symbol_size), sfile.lineno2_size, files_image}; - codeview_snarf(msc_dbg, modimage, sizeof(DWORD), sfile.symbol_size, &cvmod, file_name); + codeview_snarf(msc_dbg, pdb_file->pdb_reader ? sfile.stream : 0, modimage, sizeof(DWORD), sfile.symbol_size, + &cvmod, file_name);
if (sfile.lineno_size && sfile.lineno2_size) FIXME("Both line info present... preferring second\n"); @@ -4103,7 +4113,7 @@ static BOOL codeview_process_info(const struct process *pcs,
if (ent->SubSection == sstAlignSym) { - codeview_snarf(msc_dbg, msc_dbg->root + ent->lfo, sizeof(DWORD), ent->cb, NULL, NULL); + codeview_snarf(msc_dbg, 0, msc_dbg->root + ent->lfo, sizeof(DWORD), ent->cb, NULL, NULL);
if (SymGetOptions() & SYMOPT_LOAD_LINES) { diff --git a/dlls/dbghelp/pdb.c b/dlls/dbghelp/pdb.c index 708bc1fece3..6276ee41ee3 100644 --- a/dlls/dbghelp/pdb.c +++ b/dlls/dbghelp/pdb.c @@ -979,10 +979,180 @@ static enum method_result pdb_method_enumerate_sources(struct module_format *mod return MR_NOT_FOUND; }
+#define loc_cv_local_range (loc_user + 0) /* loc.offset contain the copy of all defrange* Codeview records following S_LOCAL */ +#define loc_cv_defrange (loc_user + 1) /* loc.register+offset contain the stream_id+stream_offset of S_LOCAL Codeview record to search into */ + +/* Some data (codeview_symbol, codeview_types...) are layed out with a 2 byte integer, + * designing length of following blob. + * Basic reading of that length + (part) of blob. + * Walker is advanced by 2 only (so that any reading inside blob is possible). + */ +static enum pdb_result pdb_reader_read_partial_blob(struct pdb_reader *pdb, struct pdb_reader_walker *walker, void *blob, unsigned blob_size) +{ + enum pdb_result result; + pdbsize_t num_read, toload; + unsigned short len; + + if ((result = pdb_reader_internal_read_advance(pdb, walker, &len, sizeof(len)))) return result; + toload = min(len, blob_size - sizeof(len)); + + if ((result = pdb_reader_read_from_stream(pdb, walker, (char*)blob + sizeof(len), toload, &num_read))) return result; + if (num_read != toload) return R_PDB_IOERROR; + *(unsigned short*)blob = len; + return R_PDB_SUCCESS; +} + +static enum pdb_result pdb_reader_alloc_and_read_full_blob(struct pdb_reader *pdb, struct pdb_reader_walker *walker, void **blob) +{ + enum pdb_result result; + unsigned short int len; + + if ((result = pdb_reader_READ(pdb, walker, &len))) return result; + if ((result = pdb_reader_alloc(pdb, len + sizeof(len), blob))) + { + walker->offset -= sizeof(len); + return result; + } + + if ((result = pdb_reader_internal_read_advance(pdb, walker, (char*)*blob + sizeof(len), len))) + { + pdb_reader_free(pdb, *blob); + walker->offset -= sizeof(len); + return result; + } + *(unsigned short int*)*blob = len; + return R_PDB_SUCCESS; +} + +/* Read the fixed part of a CodeView symbol (enough to fit inside the union codeview) */ +static enum pdb_result pdb_reader_read_partial_codeview_symbol(struct pdb_reader *pdb, struct pdb_reader_walker *walker, union codeview_symbol *cv_symbol) +{ + return pdb_reader_read_partial_blob(pdb, walker, (void*)cv_symbol, sizeof(*cv_symbol)); +} + +static enum pdb_result pdb_reader_alloc_and_read_full_codeview_symbol(struct pdb_reader *pdb, struct pdb_reader_walker *walker, + union codeview_symbol **cv_symbol) +{ + return pdb_reader_alloc_and_read_full_blob(pdb, walker, (void **)cv_symbol); +} + +static void pdb_method_location_compute(const struct module_format *modfmt, + const struct symt_function *func, + struct location *loc) +{ + enum pdb_result result; + struct pdb_reader_walker walker; + struct pdb_reader *pdb; + union codeview_symbol cv_local; + union codeview_symbol *cv_def; + DWORD64 ip = modfmt->module->process->localscope_pc; + struct location in_loc = *loc; + + loc->kind = loc_error; + loc->reg = loc_err_internal; + + if (!pdb_hack_get_main_info((struct module_format *)modfmt, &pdb, NULL)) return; + if (in_loc.kind != loc_cv_defrange || pdb_reader_walker_init(pdb, in_loc.reg, &walker)) return; + walker.offset = in_loc.offset; + + /* we have in location: in_loc.reg = stream_id, in_loc.offset offset in stream_id to point to S_LOCAL */ + if ((result = pdb_reader_read_partial_codeview_symbol(pdb, &walker, &cv_local))) return; + walker.offset += cv_local.generic.len; + + while ((result = pdb_reader_alloc_and_read_full_codeview_symbol(pdb, &walker, &cv_def)) == R_PDB_SUCCESS && + cv_def->generic.id >= S_DEFRANGE && cv_def->generic.id <= S_DEFRANGE_REGISTER_REL) + { + BOOL inside = TRUE; + + /* S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE matches full function scope... + * Assuming that if we're here, ip matches the function for which we're + * considering the S_LOCAL and S_DEFRANGE_*, there's nothing to do. + */ + if (cv_def->generic.id != S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE) + { + const struct cv_addr_range* range; + const struct cv_addr_gap* gap; + DWORD64 range_start; + + switch (cv_def->generic.id) + { + case S_DEFRANGE: range = &cv_def->defrange_v3.range; break; + case S_DEFRANGE_SUBFIELD: range = &cv_def->defrange_subfield_v3.range; break; + case S_DEFRANGE_REGISTER: range = &cv_def->defrange_register_v3.range; break; + case S_DEFRANGE_FRAMEPOINTER_REL: range = &cv_def->defrange_frameptrrel_v3.range; break; + case S_DEFRANGE_SUBFIELD_REGISTER: range = &cv_def->defrange_subfield_register_v3.range; break; + case S_DEFRANGE_REGISTER_REL: range = &cv_def->defrange_registerrel_v3.range; break; + default: range = NULL; + } + + /* check if inside range */ + if ((result = pdb_reader_get_segment_address(pdb, range->isectStart, range->offStart, &range_start))) + { + pdb_reader_free(pdb, cv_def); + return; + } + inside = range_start <= ip && ip < range_start + range->cbRange; + + /* the gaps describe part which shall be excluded from range */ + for (gap = (const void*)(range + 1); + inside && (const char*)(gap + 1) <= (const char*)cv_def + sizeof(cv_def->generic.len) + cv_def->generic.len; + gap++) + { + if (func->ranges[0].low + gap->gapStartOffset <= ip && + ip < func->ranges[0].low + gap->gapStartOffset + gap->cbRange) + inside = FALSE; + } + } + if (!inside) + { + pdb_reader_free(pdb, cv_def); + continue; + } + + switch (cv_def->generic.id) + { + case S_DEFRANGE: + case S_DEFRANGE_SUBFIELD: + default: + WARN("Unsupported defrange %d\n", cv_def->generic.id); + loc->kind = loc_error; + loc->reg = loc_err_internal; + break; + case S_DEFRANGE_SUBFIELD_REGISTER: + WARN("sub-field part not handled\n"); + /* fall through */ + case S_DEFRANGE_REGISTER: + loc->kind = loc_register; + loc->reg = cv_def->defrange_register_v3.reg; + break; + case S_DEFRANGE_REGISTER_REL: + loc->kind = loc_regrel; + loc->reg = cv_def->defrange_registerrel_v3.baseReg; + loc->offset = cv_def->defrange_registerrel_v3.offBasePointer; + break; + case S_DEFRANGE_FRAMEPOINTER_REL: + loc->kind = loc_regrel; + loc->reg = modfmt->module->cpu->frame_regno; + loc->offset = cv_def->defrange_frameptrrel_v3.offFramePointer; + break; + case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: + loc->kind = loc_regrel; + loc->reg = modfmt->module->cpu->frame_regno; + loc->offset = cv_def->defrange_frameptr_relfullscope_v3.offFramePointer; + break; + } + pdb_reader_free(pdb, cv_def); + return; + } + if (result == R_PDB_SUCCESS) pdb_reader_free(pdb, cv_def); + loc->kind = loc_error; + loc->reg = loc_err_out_of_scope; +} + static struct module_format_vtable pdb_module_format_vtable = { NULL,/*pdb_module_remove*/ - NULL,/*pdb_location_compute*/ + pdb_method_location_compute, pdb_method_get_line_from_address, pdb_method_advance_line_info, pdb_method_enumerate_lines, @@ -1000,7 +1170,6 @@ struct pdb_reader *pdb_hack_reader_init(struct module *module, HANDLE file, cons pdb->module = module; /* hack (copy old pdb methods until they are moved here) */ pdb_module_format_vtable.remove = module->format_info[DFI_PDB]->vtable->remove; - pdb_module_format_vtable.loc_compute = module->format_info[DFI_PDB]->vtable->loc_compute;
module->format_info[DFI_PDB]->vtable = &pdb_module_format_vtable; return pdb;
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dbghelp/dbghelp_private.h | 2 ++ dlls/dbghelp/symbol.c | 5 ++--- dlls/dbghelp/type.c | 8 +++++++- 3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 66282a2e6e9..f2c74f05d24 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -972,6 +972,8 @@ extern BOOL lineinfo_set_nameA(struct process* pcs, struct lineinfo_t* i extern void symt_init_basic(struct module* module); extern BOOL symt_get_info(struct module* module, const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo); +extern BOOL symt_get_info_from_index(struct module* module, DWORD index, + IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo); extern struct symt_basic* symt_get_basic(enum BasicType, unsigned size); extern struct symt_udt* diff --git a/dlls/dbghelp/symbol.c b/dlls/dbghelp/symbol.c index 65eb4fd3106..784f88beb08 100644 --- a/dlls/dbghelp/symbol.c +++ b/dlls/dbghelp/symbol.c @@ -708,8 +708,7 @@ static BOOL symt_fill_sym_info(struct module_pair* pair, sym_info->Reserved[0] = sym_info->Reserved[1] = 0; if (!symt_get_info(pair->effective, sym, TI_GET_LENGTH, &size) && (!sym_info->TypeIndex || - !symt_get_info(pair->effective, symt_index2ptr(pair->effective, sym_info->TypeIndex), - TI_GET_LENGTH, &size))) + !symt_get_info_from_index(pair->effective, sym_info->TypeIndex, TI_GET_LENGTH, &size))) size = 0; sym_info->Size = (DWORD)size; sym_info->ModBase = pair->requested->module.BaseOfImage; @@ -991,7 +990,7 @@ static void symt_get_length(struct module* module, const struct symt* symt, ULON return;
if (symt_get_info(module, symt, TI_GET_TYPE, &type_index) && - symt_get_info(module, symt_index2ptr(module, type_index), TI_GET_LENGTH, size)) return; + symt_get_info_from_index(module, type_index, TI_GET_LENGTH, size)) return; *size = 1; /* no size info */ }
diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index 8be905116c7..97abb60f64d 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -1111,6 +1111,12 @@ BOOL symt_get_info(struct module* module, const struct symt* type, return TRUE; }
+BOOL symt_get_info_from_index(struct module* module, DWORD index, + IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo) +{ + return symt_get_info(module, symt_index2ptr(module, index), req, pInfo); +} + /****************************************************************** * SymGetTypeInfo (DBGHELP.@) * @@ -1122,7 +1128,7 @@ BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase, struct module_pair pair;
if (!module_init_pair(&pair, hProcess, ModBase)) return FALSE; - return symt_get_info(pair.effective, symt_index2ptr(pair.effective, TypeId), GetType, pInfo); + return symt_get_info_from_index(pair.effective, TypeId, GetType, pInfo); }
/******************************************************************