(another global vs relative-to mismatch)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/msc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index c0d09b75c56..c481c762b1d 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -2246,12 +2246,12 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg,
case S_BLOCK32_ST: block = symt_open_func_block(msc_dbg->module, curr_func, block, - codeview_get_address(msc_dbg, sym->block_v1.segment, sym->block_v1.offset), + codeview_get_address(msc_dbg, sym->block_v1.segment, sym->block_v1.offset) - curr_func->address, sym->block_v1.length); break; case S_BLOCK32: block = symt_open_func_block(msc_dbg->module, curr_func, block, - codeview_get_address(msc_dbg, sym->block_v3.segment, sym->block_v3.offset), + codeview_get_address(msc_dbg, sym->block_v3.segment, sym->block_v3.offset) - curr_func->address, sym->block_v3.length); break;
Old version of PDB files can have a stream #4 which is not an IPI stream Available documentation isn't 100% clear about when IPI has been introduced. So decide that IPI is present when header of stream looks like a type stream header.
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/msc.c | 6 ++++-- tools/winedump/pdb.c | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/dlls/dbghelp/msc.c b/dlls/dbghelp/msc.c index c481c762b1d..4e44655deb5 100644 --- a/dlls/dbghelp/msc.c +++ b/dlls/dbghelp/msc.c @@ -3047,6 +3047,7 @@ static BOOL pdb_init_type_parse(const struct msc_debug_info* msc_dbg, break; default: ERR("-Unknown type info version %d\n", types.version); + return FALSE; }
ctp->module = msc_dbg->module; @@ -3324,6 +3325,7 @@ static BOOL pdb_process_internal(const struct process* pcs, BYTE* file; int header_size = 0; PDB_STREAM_INDEXES* psi; + BOOL ipi_ok;
pdb_convert_symbols_header(&symbols, &header_size, symbols_image); switch (symbols.version) @@ -3363,7 +3365,7 @@ static BOOL pdb_process_internal(const struct process* pcs, pdb_process_types(msc_dbg, pdb_file);
ipi_image = pdb_read_file(pdb_file, 4); - pdb_init_type_parse(msc_dbg, &ipi_ctp, ipi_image); + ipi_ok = pdb_init_type_parse(msc_dbg, &ipi_ctp, ipi_image);
/* Read global symbol table */ globalimage = pdb_read_file(pdb_file, symbols.gsym_file); @@ -3387,7 +3389,7 @@ static BOOL pdb_process_internal(const struct process* pcs, modimage = pdb_read_file(pdb_file, sfile.file); if (modimage) { - struct cv_module_snarf cvmod = {&ipi_ctp, (const void*)(modimage + sfile.symbol_size), sfile.lineno2_size, + struct cv_module_snarf cvmod = {ipi_ok ? &ipi_ctp : NULL, (const void*)(modimage + sfile.symbol_size), sfile.lineno2_size, files_image + 12, files_size}; codeview_snarf(msc_dbg, modimage, sizeof(DWORD), sfile.symbol_size, &cvmod, TRUE); diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c index ed4877cd10a..958a13f5e1c 100644 --- a/tools/winedump/pdb.c +++ b/tools/winedump/pdb.c @@ -54,6 +54,21 @@ struct pdb_reader DWORD file_used[1024]; };
+static inline BOOL has_file_been_read(struct pdb_reader* reader, unsigned file_nr) +{ + return reader->file_used[file_nr / 32] & (1 << (file_nr % 32)); +} + +static inline void mark_file_been_read(struct pdb_reader* reader, unsigned file_nr) +{ + reader->file_used[file_nr / 32] |= 1 << (file_nr % 32); +} + +static inline void clear_file_been_read(struct pdb_reader* reader, unsigned file_nr) +{ + reader->file_used[file_nr / 32] &= ~(1 << (file_nr % 32)); +} + static void* pdb_jg_read(const struct PDB_JG_HEADER* pdb, const WORD* block_list, int size) { int i, nBlocks; @@ -78,7 +93,7 @@ static void* pdb_jg_read_file(struct pdb_reader* reader, DWORD file_nr)
if (!reader->u.jg.toc || file_nr >= reader->u.jg.toc->num_files) return NULL;
- reader->file_used[file_nr / 32] |= 1 << (file_nr % 32); + mark_file_been_read(reader, file_nr); if (reader->u.jg.toc->file[file_nr].size == 0 || reader->u.jg.toc->file[file_nr].size == 0xFFFFFFFF) return NULL; @@ -125,7 +140,7 @@ static void pdb_exit(struct pdb_reader* reader)
for (i = 0; i < pdb_get_num_files(reader); i++) { - if (reader->file_used[i / 32] & (1 << (i % 32))) continue; + if (has_file_been_read(reader, i)) continue;
file = reader->read_file(reader, i); if (!file) continue; @@ -615,7 +630,14 @@ static void pdb_dump_types_hash(struct pdb_reader* reader, unsigned file, const static void pdb_dump_types(struct pdb_reader* reader, unsigned strmidx, const char* strmname) { PDB_TYPES* types = NULL; + BOOL used = has_file_been_read(reader, strmidx);
+ if (pdb_get_file_size(reader, strmidx) < sizeof(*types)) + { + if (strmidx == 2) + printf("-Too small type header\n"); + return; + } types = reader->read_file(reader, strmidx); if (!types) return;
@@ -628,7 +650,12 @@ static void pdb_dump_types(struct pdb_reader* reader, unsigned strmidx, const ch case 20040203: /* VC 8.0 */ break; default: - printf("-Unknown type info version %d\n", types->version); + /* IPI stream is not always present in older PDB files */ + if (strmidx == 2) + printf("-Unknown type info version %d\n", types->version); + free(types); + if (used) clear_file_been_read(reader, strmidx); + return; }
/* Read type table */ @@ -870,7 +897,7 @@ static void* pdb_ds_read_file(struct pdb_reader* reader, DWORD file_number)
if (!reader->u.ds.toc || file_number >= reader->u.ds.toc->num_files) return NULL;
- reader->file_used[file_number / 32] |= 1 << (file_number % 32); + mark_file_been_read(reader, file_number); if (reader->u.ds.toc->file_size[file_number] == 0 || reader->u.ds.toc->file_size[file_number] == 0xFFFFFFFF) return NULL; @@ -932,7 +959,7 @@ static void pdb_ds_dump(void) * - segments * - extended FPO data */ - reader.file_used[0] |= 1; /* mark stream #0 as read */ + mark_file_been_read(&reader, 0); /* mark stream #0 as read */ reader.u.ds.root = reader.read_file(&reader, 1); if (reader.u.ds.root) {
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- include/wine/mscvpdb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h index 9a733333837..f7dcbcb6625 100644 --- a/include/wine/mscvpdb.h +++ b/include/wine/mscvpdb.h @@ -603,7 +603,7 @@ union codeview_fieldtype cv_typ_t type; unsigned short int offset; /* numeric leaf */ #if 0 - unsigned char name[1]; + char name[1]; #endif } member_v3; @@ -1986,7 +1986,7 @@ union codeview_symbol { unsigned short int len; unsigned short int id; - unsigned char name[1]; + char name[1]; } unamespace_v3; };
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- include/wine/mscvpdb.h | 37 +++++++++++++++++++++++++++++++++++++ tools/winedump/msc.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+)
diff --git a/include/wine/mscvpdb.h b/include/wine/mscvpdb.h index f7dcbcb6625..b0021ed3c25 100644 --- a/include/wine/mscvpdb.h +++ b/include/wine/mscvpdb.h @@ -482,6 +482,17 @@ union codeview_reftype unsigned num; cv_typ_t drvdcls[1]; } derived_v2; + + struct + { + unsigned short int len; + unsigned short int id; + cv_typ_t type; + cv_typ_t baseVftable; + unsigned offsetInObjectLayout; + unsigned cbstr; + char names[1]; /* array of len 0-terminated strings (size of cbstr in char:s) */ + } vftable_v3; };
union codeview_fieldtype @@ -1287,6 +1298,7 @@ union codeview_fieldtype #define LF_METHOD_V3 0x150f #define LF_NESTTYPE_V3 0x1510 #define LF_ONEMETHOD_V3 0x1511 +#define LF_VFTABLE_V3 0x151d
/* leaves found in second type type (aka IPI) * for simplicity, stored in the same union as other TPI leaves @@ -1988,6 +2000,30 @@ union codeview_symbol unsigned short int id; char name[1]; } unamespace_v3; + + struct + { + unsigned short int len; + unsigned short int id; + unsigned int pParent; + unsigned int pEnd; + unsigned int length; + unsigned int scf; /* CV_SEPCODEFLAGS */ + unsigned int off; + unsigned int offParent; + unsigned short int sect; + unsigned short int sectParent; + } sepcode_v3; + + struct + { + unsigned short int len; + unsigned short int id; + unsigned int off; + unsigned short int seg; + unsigned short int csz; /* number of bytes in following array */ + char rgsz[1]; /* array of null terminated strings (bounded by csz) */ + } annotation_v3; };
enum BinaryAnnotationOpcode @@ -2061,6 +2097,7 @@ enum BinaryAnnotationOpcode #define S_GTHREAD32_ST 0x100f #define S_FRAMEPROC 0x1012 #define S_COMPILE2_ST 0x1013 +#define S_ANNOTATION 0x1019 #define S_UNAMESPACE_ST 0x1029
#define S_OBJNAME 0x1101 diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index 40daf4d50d5..cd91ea63634 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -1102,6 +1102,20 @@ static void codeview_dump_one_type(unsigned curr_type, const union codeview_type printf("\n"); break;
+ case LF_VFTABLE_V3: + printf("\t%x => VFTable V3 base:%x baseVfTable:%x offset%u\n", + curr_type, reftype->vftable_v3.type, reftype->vftable_v3.baseVftable, reftype->vftable_v3.offsetInObjectLayout); + { + const char* str = reftype->vftable_v3.names; + const char* last = str + reftype->vftable_v3.cbstr; + while (str < last) + { + printf("\t\t%s\n", str); + str += strlen(str) + 1; + } + } + break; + /* types from IPI (aka #4) stream */ case LF_FUNC_ID: printf("\t%x => FuncId %s scopeId:%04x type:%04x\n", @@ -1867,6 +1881,24 @@ BOOL codeview_dump_symbols(const void* root, unsigned long size) printf("UNameSpace V3 '%s'\n", sym->unamespace_v3.name); break;
+ case S_SEPCODE: + printf("SepCode V3 pParent:%x pEnd:%x separated:%04x:%08x (#%u) from %04x:%08x\n", + sym->sepcode_v3.pParent, sym->sepcode_v3.pEnd, + sym->sepcode_v3.sect, sym->sepcode_v3.off, sym->sepcode_v3.length, + sym->sepcode_v3.sectParent, sym->sepcode_v3.offParent); + break; + + case S_ANNOTATION: + printf("Annotation V3 %04x:%08x\n", + sym->annotation_v3.seg, sym->annotation_v3.off); + { + const char* ptr = sym->annotation_v3.rgsz; + const char* last = ptr + sym->annotation_v3.csz; + for (; ptr < last; ptr += strlen(ptr) + 1) + printf("\t%s\n", ptr); + } + break; + default: printf("\n\t\t>>> Unsupported symbol-id %x sz=%d\n", sym->generic.id, sym->generic.len + 2); dump_data((const void*)sym, sym->generic.len + 2, " ");
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- tools/winedump/debug.c | 4 ++-- tools/winedump/lib.c | 2 +- tools/winedump/msc.c | 6 +++--- tools/winedump/pdb.c | 4 ++-- tools/winedump/winedump.h | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/tools/winedump/debug.c b/tools/winedump/debug.c index c2efeb24340..b49c6337494 100644 --- a/tools/winedump/debug.c +++ b/tools/winedump/debug.c @@ -135,7 +135,7 @@ static BOOL dump_cv_sst_global_pub(const OMFDirEntry* omfde) symbols = PRD(fileoffset + sizeof(OMFSymHash), header->cbSymbol); if (!symbols) {printf("Can't OMF-SymHash details, aborting\n"); return FALSE;}
- codeview_dump_symbols(symbols, header->cbSymbol); + codeview_dump_symbols(symbols, 0, header->cbSymbol);
return TRUE; } @@ -320,7 +320,7 @@ static BOOL dump_cv_sst_align_sym(const OMFDirEntry* omfde)
if (!rawdata) {printf("Can't get srcAlignSym subsection details, aborting\n");return FALSE;} if (omfde->cb < sizeof(DWORD)) return TRUE; - codeview_dump_symbols(rawdata + sizeof(DWORD), omfde->cb - sizeof(DWORD)); + codeview_dump_symbols(rawdata, sizeof(DWORD), omfde->cb);
return TRUE; } diff --git a/tools/winedump/lib.c b/tools/winedump/lib.c index 430ec2d4de7..4000e8679cf 100644 --- a/tools/winedump/lib.c +++ b/tools/winedump/lib.c @@ -97,7 +97,7 @@ static void dump_long_import(const void *base, const IMAGE_SECTION_HEADER *ish, { const char *imp_debugS = (const char *)base + ish[i].PointerToRawData;
- codeview_dump_symbols(imp_debugS, ish[i].SizeOfRawData); + codeview_dump_symbols(imp_debugS, 0, ish[i].SizeOfRawData); printf("\n"); } } diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index cd91ea63634..f058eaf0b36 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -1303,7 +1303,7 @@ static void dump_binannot(const unsigned char* ba, const char* last, const char* } }
-BOOL codeview_dump_symbols(const void* root, unsigned long size) +BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long size) { unsigned int i; int length; @@ -1313,12 +1313,12 @@ BOOL codeview_dump_symbols(const void* root, unsigned long size) * Loop over the different types of records and whenever we * find something we are interested in, record it and move on. */ - for (i = 0; i < size; i += length) + for (i = start; i < size; i += length) { const union codeview_symbol* sym = (const union codeview_symbol*)((const char*)root + i); length = sym->generic.len + 2; if (!sym->generic.id || length < 4) break; - printf("\t%04x => ", i + 4); /* ref is made after id and len */ + printf("\t%04x => ", i);
switch (sym->generic.id) { diff --git a/tools/winedump/pdb.c b/tools/winedump/pdb.c index 958a13f5e1c..7badc8a32e2 100644 --- a/tools/winedump/pdb.c +++ b/tools/winedump/pdb.c @@ -473,7 +473,7 @@ static void pdb_dump_symbols(struct pdb_reader* reader, PDB_STREAM_INDEXES* sidx if (modimage) { printf("\t------------globals-------------\n"); - codeview_dump_symbols(modimage, pdb_get_file_size(reader, symbols->gsym_file)); + codeview_dump_symbols(modimage, 0, pdb_get_file_size(reader, symbols->gsym_file)); free(modimage); }
@@ -588,7 +588,7 @@ static void pdb_dump_symbols(struct pdb_reader* reader, PDB_STREAM_INDEXES* sidx int total_size = pdb_get_file_size(reader, file_nr);
if (symbol_size) - codeview_dump_symbols((const char*)modimage + sizeof(DWORD), symbol_size); + codeview_dump_symbols((const char*)modimage, sizeof(DWORD), symbol_size);
/* line number info */ if (lineno_size) diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h index 236ce6dede3..6013d3caae6 100644 --- a/tools/winedump/winedump.h +++ b/tools/winedump/winedump.h @@ -259,7 +259,7 @@ void tlb_dump(void); enum FileSig get_kind_nls(void); void nls_dump(void);
-BOOL codeview_dump_symbols(const void* root, unsigned long size); +BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long size); BOOL codeview_dump_types_from_offsets(const void* table, const DWORD* offsets, unsigned num_types); BOOL codeview_dump_types_from_block(const void* table, unsigned long len); void codeview_dump_linetab(const char* linetab, BOOL pascal_str, const char* pfx);
(it's not really relevant when inline sites are present)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- tools/winedump/msc.c | 62 ++++++++++++++++++++------------------------------ 1 file changed, 25 insertions(+), 37 deletions(-)
diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index f058eaf0b36..2fefa36381a 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -1307,7 +1307,6 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long { unsigned int i; int length; - char* curr_func = NULL; int nest_block = 0; /* * Loop over the different types of records and whenever we @@ -1385,7 +1384,6 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long p_string(&sym->thunk_v1.p_name), sym->thunk_v1.segment, sym->thunk_v1.offset, sym->thunk_v1.thunk_len, sym->thunk_v1.thtype); - curr_func = xstrdup(p_string(&sym->thunk_v1.p_name)); break;
case S_THUNK32: @@ -1393,7 +1391,6 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->thunk_v3.name, sym->thunk_v3.segment, sym->thunk_v3.offset, sym->thunk_v3.thunk_len, sym->thunk_v3.thtype); - curr_func = xstrdup(sym->thunk_v3.name); break;
/* Global and static functions */ @@ -1409,10 +1406,9 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->proc_v1.debug_start, sym->proc_v1.debug_end); if (nest_block) { - printf(">>> prev func '%s' still has nest_block %u count\n", curr_func, nest_block); + printf(">>> prev func still has nest_block %u count\n", nest_block); nest_block = 0; } - curr_func = xstrdup(p_string(&sym->proc_v1.p_name)); /* EPP unsigned int pparent; */ /* EPP unsigned int pend; */ /* EPP unsigned int next; */ @@ -1430,10 +1426,9 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->proc_v2.debug_start, sym->proc_v2.debug_end); if (nest_block) { - printf(">>> prev func '%s' still has nest_block %u count\n", curr_func, nest_block); + printf(">>> prev func still has nest_block %u count\n", nest_block); nest_block = 0; } - curr_func = xstrdup(p_string(&sym->proc_v2.p_name)); /* EPP unsigned int pparent; */ /* EPP unsigned int pend; */ /* EPP unsigned int next; */ @@ -1451,10 +1446,9 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->proc_v3.debug_start, sym->proc_v3.debug_end); if (nest_block) { - printf(">>> prev func '%s' still has nest_block %u count\n", curr_func, nest_block); + printf(">>> prev func still has nest_block %u count\n", nest_block); nest_block = 0; } - curr_func = xstrdup(sym->proc_v3.name); /* EPP unsigned int pparent; */ /* EPP unsigned int pend; */ /* EPP unsigned int next; */ @@ -1462,59 +1456,57 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long
/* Function parameters and stack variables */ case S_BPREL32_16t: - printf("BP-relative V1: '%s' @%d type:%x (%s)\n", + printf("BP-relative V1: '%s' @%d type:%x\n", p_string(&sym->stack_v1.p_name), - sym->stack_v1.offset, sym->stack_v1.symtype, curr_func); + sym->stack_v1.offset, sym->stack_v1.symtype); break;
case S_BPREL32_ST: - printf("BP-relative V2: '%s' @%d type:%x (%s)\n", + printf("BP-relative V2: '%s' @%d type:%x\n", p_string(&sym->stack_v2.p_name), - sym->stack_v2.offset, sym->stack_v2.symtype, curr_func); + sym->stack_v2.offset, sym->stack_v2.symtype); break;
case S_BPREL32: - printf("BP-relative V3: '%s' @%d type:%x (in %s)\n", + printf("BP-relative V3: '%s' @%d type:%x\n", sym->stack_v3.name, sym->stack_v3.offset, - sym->stack_v3.symtype, curr_func); + sym->stack_v3.symtype); break;
case S_REGREL32: - printf("Reg-relative V3: '%s' @%d type:%x reg:%x (in %s)\n", + printf("Reg-relative V3: '%s' @%d type:%x reg:%x\n", sym->regrel_v3.name, sym->regrel_v3.offset, - sym->regrel_v3.symtype, sym->regrel_v3.reg, curr_func); + sym->regrel_v3.symtype, sym->regrel_v3.reg); break;
case S_REGISTER_16t: - printf("Register V1 '%s' in %s type:%x register:%x\n", + printf("Register V1 '%s' type:%x register:%x\n", p_string(&sym->register_v1.p_name), - curr_func, sym->register_v1.reg, sym->register_v1.type); + sym->register_v1.reg, sym->register_v1.type); break;
case S_REGISTER_ST: - printf("Register V2 '%s' in %s type:%x register:%x\n", + printf("Register V2 '%s' type:%x register:%x\n", p_string(&sym->register_v2.p_name), - curr_func, sym->register_v2.reg, sym->register_v2.type); + sym->register_v2.reg, sym->register_v2.type); break;
case S_REGISTER: - printf("Register V3 '%s' in %s type:%x register:%x\n", - sym->register_v3.name, - curr_func, sym->register_v3.reg, sym->register_v3.type); + printf("Register V3 '%s' type:%x register:%x\n", + sym->register_v3.name, sym->register_v3.reg, sym->register_v3.type); break;
case S_BLOCK32_ST: - printf("Block V1 '%s' in '%s' (%04x:%08x#%08x)\n", + printf("Block V1 '%s' (%04x:%08x#%08x)\n", p_string(&sym->block_v1.p_name), - curr_func, sym->block_v1.segment, sym->block_v1.offset, sym->block_v1.length); nest_block++; break;
case S_BLOCK32: - printf("Block V3 '%s' in '%s' (%04x:%08x#%08x) parent:%u end:%x\n", - sym->block_v3.name, curr_func, + printf("Block V3 '%s' (%04x:%08x#%08x) parent:%u end:%x\n", + sym->block_v3.name, sym->block_v3.segment, sym->block_v3.offset, sym->block_v3.length, sym->block_v3.parent, sym->block_v3.end); nest_block++; @@ -1544,11 +1536,7 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long printf("End-Of block (%u)\n", nest_block); } else - { - printf("End-Of %s\n", curr_func); - free(curr_func); - curr_func = NULL; - } + printf("End-Of function\n"); break;
case S_COMPILE: @@ -1642,14 +1630,14 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long break;
case S_LABEL32_ST: - printf("Label V1 '%s' in '%s' (%04x:%08x)\n", + printf("Label V1 '%s' (%04x:%08x)\n", p_string(&sym->label_v1.p_name), - curr_func, sym->label_v1.segment, sym->label_v1.offset); + sym->label_v1.segment, sym->label_v1.offset); break;
case S_LABEL32: - printf("Label V3 '%s' in '%s' (%04x:%08x) flag:%x\n", - sym->label_v3.name, curr_func, sym->label_v3.segment, + printf("Label V3 '%s' (%04x:%08x) flag:%x\n", + sym->label_v3.name, sym->label_v3.segment, sym->label_v3.offset, sym->label_v3.flags); break;
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- tools/winedump/msc.c | 84 ++++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 41 deletions(-)
diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index 2fefa36381a..07691e5be6a 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -1196,13 +1196,13 @@ BOOL codeview_dump_types_from_block(const void* table, unsigned long len) return TRUE; }
-static void dump_defrange(const struct cv_addr_range* range, const void* last, const char* pfx) +static void dump_defrange(const struct cv_addr_range* range, const void* last, unsigned indent) { const struct cv_addr_gap* gap;
- printf("%s%04x:%08x range:#%x\n", pfx, range->isectStart, range->offStart, range->cbRange); + printf("%*s\- %04x:%08x range:#%x\n", indent, "", range->isectStart, range->offStart, range->cbRange); for (gap = (const struct cv_addr_gap*)(range + 1); (const void*)(gap + 1) <= last; ++gap) - printf("%s\toffset:%x range:#%x\n", pfx, gap->gapStartOffset, gap->cbRange); + printf("%*s | offset:%x range:#%x\n", indent, "", gap->gapStartOffset, gap->cbRange); }
/* return address of first byte after the symbol */ @@ -1240,7 +1240,7 @@ static inline int binannot_getsigned(unsigned i) return (i & 1) ? -(int)(i >> 1) : (i >> 1); }
-static void dump_binannot(const unsigned char* ba, const char* last, const char* pfx) +static void dump_binannot(const unsigned char* ba, const char* last, unsigned indent) { while (ba < (const unsigned char*)last) { @@ -1249,56 +1249,56 @@ static void dump_binannot(const unsigned char* ba, const char* last, const char* { case BA_OP_Invalid: /* not clear if param? */ - printf("%sInvalid\n", pfx); + printf("%*s | Invalid\n", indent, ""); break; case BA_OP_CodeOffset: - printf("%sCodeOffset %u\n", pfx, binannot_uncompress(&ba)); + printf("%*s | CodeOffset %u\n", indent, "", binannot_uncompress(&ba)); break; case BA_OP_ChangeCodeOffsetBase: - printf("%sChangeCodeOffsetBase %u\n", pfx, binannot_uncompress(&ba)); + printf("%*s | ChangeCodeOffsetBase %u\n", indent, "", binannot_uncompress(&ba)); break; case BA_OP_ChangeCodeOffset: - printf("%sChangeCodeOffset %u\n", pfx, binannot_uncompress(&ba)); + printf("%*s | ChangeCodeOffset %u\n", indent, "", binannot_uncompress(&ba)); break; case BA_OP_ChangeCodeLength: - printf("%sChangeCodeLength %u\n", pfx, binannot_uncompress(&ba)); + printf("%*s | ChangeCodeLength %u\n", indent, "", binannot_uncompress(&ba)); break; case BA_OP_ChangeFile: - printf("%sChangeFile %u\n", pfx, binannot_uncompress(&ba)); + printf("%*s | ChangeFile %u\n", indent, "", binannot_uncompress(&ba)); break; case BA_OP_ChangeLineOffset: - printf("%sChangeLineOffset %d\n", pfx, binannot_getsigned(binannot_uncompress(&ba))); + printf("%*s | ChangeLineOffset %d\n", indent, "", binannot_getsigned(binannot_uncompress(&ba))); break; case BA_OP_ChangeLineEndDelta: - printf("%sChangeLineEndDelta %u\n", pfx, binannot_uncompress(&ba)); + printf("%*s | ChangeLineEndDelta %u\n", indent, "", binannot_uncompress(&ba)); break; case BA_OP_ChangeRangeKind: - printf("%sChangeRangeKind %u\n", pfx, binannot_uncompress(&ba)); + printf("%*s | ChangeRangeKind %u\n", indent, "", binannot_uncompress(&ba)); break; case BA_OP_ChangeColumnStart: - printf("%sChangeColumnStart %u\n", pfx, binannot_uncompress(&ba)); + printf("%*s | ChangeColumnStart %u\n", indent, "", binannot_uncompress(&ba)); break; case BA_OP_ChangeColumnEndDelta: - printf("%sChangeColumnEndDelta %u\n", pfx, binannot_uncompress(&ba)); + printf("%*s | ChangeColumnEndDelta %u\n", indent, "", binannot_uncompress(&ba)); break; case BA_OP_ChangeCodeOffsetAndLineOffset: { unsigned p1 = binannot_uncompress(&ba); - printf("%sChangeCodeOffsetAndLineOffset %u %u (0x%x)\n", pfx, p1 & 0xf, binannot_getsigned(p1 >> 4), p1); + printf("%*s | ChangeCodeOffsetAndLineOffset %u %u (0x%x)\n", indent, "", p1 & 0xf, binannot_getsigned(p1 >> 4), p1); } break; case BA_OP_ChangeCodeLengthAndCodeOffset: { unsigned p1 = binannot_uncompress(&ba); unsigned p2 = binannot_uncompress(&ba); - printf("%sChangeCodeLengthAndCodeOffset %u %u\n", pfx, p1, p2); + printf("%*s | ChangeCodeLengthAndCodeOffset %u %u\n", indent, "", p1, p2); } break; case BA_OP_ChangeColumnEnd: - printf("%sChangeColumnEnd %u\n", pfx, binannot_uncompress(&ba)); + printf("%*s | ChangeColumnEnd %u\n", indent, "", binannot_uncompress(&ba)); break;
- default: printf("%sUnsupported op %d %x\n", pfx, opcode, opcode); /* may cause issues because of param */ + default: printf(">>> Unsupported op %d %x\n", opcode, opcode); /* may cause issues because of param */ } } } @@ -1315,9 +1315,11 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long for (i = start; i < size; i += length) { const union codeview_symbol* sym = (const union codeview_symbol*)((const char*)root + i); + unsigned indent; + length = sym->generic.len + 2; if (!sym->generic.id || length < 4) break; - printf("\t%04x => ", i); + indent = printf(" %04x => ", i);
switch (sym->generic.id) { @@ -1402,8 +1404,8 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->proc_v1.segment, sym->proc_v1.offset, sym->proc_v1.proc_len, sym->proc_v1.proctype, sym->proc_v1.flags); - printf("\t\tDebug: start=%08x end=%08x\n", - sym->proc_v1.debug_start, sym->proc_v1.debug_end); + printf("%*s\- Debug: start=%08x end=%08x\n", + indent, "", sym->proc_v1.debug_start, sym->proc_v1.debug_end); if (nest_block) { printf(">>> prev func still has nest_block %u count\n", nest_block); @@ -1422,8 +1424,8 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->proc_v2.segment, sym->proc_v2.offset, sym->proc_v2.proc_len, sym->proc_v2.proctype, sym->proc_v2.flags); - printf("\t\tDebug: start=%08x end=%08x\n", - sym->proc_v2.debug_start, sym->proc_v2.debug_end); + printf("%*s\- Debug: start=%08x end=%08x\n", + indent, "", sym->proc_v2.debug_start, sym->proc_v2.debug_end); if (nest_block) { printf(">>> prev func still has nest_block %u count\n", nest_block); @@ -1442,8 +1444,8 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->proc_v3.segment, sym->proc_v3.offset, sym->proc_v3.proc_len, sym->proc_v3.proctype, sym->proc_v3.flags); - printf("\t\tDebug: start=%08x end=%08x\n", - sym->proc_v3.debug_start, sym->proc_v3.debug_end); + printf("%*s\- Debug: start=%08x end=%08x\n", + indent, "", sym->proc_v3.debug_start, sym->proc_v3.debug_end); if (nest_block) { printf(">>> prev func still has nest_block %u count\n", nest_block); @@ -1559,7 +1561,7 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long const char* ptr = sym->compile2_v2.p_name.name + sym->compile2_v2.p_name.namelen; while (*ptr) { - printf("\t\t%s => ", ptr); ptr += strlen(ptr) + 1; + printf("%*s| %s => ", indent, "", ptr); ptr += strlen(ptr) + 1; printf("%s\n", ptr); ptr += strlen(ptr) + 1; } } @@ -1577,7 +1579,7 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long const char* ptr = sym->compile2_v3.name + strlen(sym->compile2_v3.name) + 1; while (*ptr) { - printf("\t\t%s => ", ptr); ptr += strlen(ptr) + 1; + printf("%*s| %s => ", indent, "", ptr); ptr += strlen(ptr) + 1; printf("%s\n", ptr); ptr += strlen(ptr) + 1; } } @@ -1598,12 +1600,12 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long const char* x1 = (const char*)sym + 4 + 1; const char* x2;
- printf("\tTool conf V3\n"); + printf("Tool conf V3\n"); while (*x1) { x2 = x1 + strlen(x1) + 1; if (!*x2) break; - printf("\t\t%s: %s\n", x1, x2); + printf("%*s| %s: %s\n", indent, "", x1, x2); x1 = x2 + strlen(x2) + 1; } } @@ -1696,7 +1698,7 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long
pname = PSTRING(sym, length); length += (pname->namelen + 1 + 3) & ~3; - printf("\t%08x %08x %08x '%s'\n", + printf("%08x %08x %08x '%s'\n", *(((const DWORD*)sym) + 1), *(((const DWORD*)sym) + 2), *(((const DWORD*)sym) + 3), p_string(pname)); } @@ -1766,22 +1768,22 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long
case S_DEFRANGE: printf("DefRange dia:%x\n", sym->defrange_v3.program); - dump_defrange(&sym->defrange_v3.range, get_last(sym), "\t\t"); + dump_defrange(&sym->defrange_v3.range, get_last(sym), indent); break; case S_DEFRANGE_SUBFIELD: printf("DefRange-subfield V3 dia:%x off-parent:%x\n", sym->defrange_subfield_v3.program, sym->defrange_subfield_v3.offParent); - dump_defrange(&sym->defrange_subfield_v3.range, get_last(sym), "\t\t"); + dump_defrange(&sym->defrange_subfield_v3.range, get_last(sym), indent); break; case S_DEFRANGE_REGISTER: printf("DefRange-register V3 reg:%x attr-unk:%x\n", sym->defrange_register_v3.reg, sym->defrange_register_v3.attr); - dump_defrange(&sym->defrange_register_v3.range, get_last(sym), "\t\t"); + dump_defrange(&sym->defrange_register_v3.range, get_last(sym), indent); break; case S_DEFRANGE_FRAMEPOINTER_REL: printf("DefRange-framepointer-rel V3 offFP:%x\n", sym->defrange_frameptrrel_v3.offFramePointer); - dump_defrange(&sym->defrange_frameptrrel_v3.range, get_last(sym), "\t\t"); + dump_defrange(&sym->defrange_frameptrrel_v3.range, get_last(sym), indent); break; case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE: printf("DefRange-framepointer-rel-fullscope V3 offFP:%x\n", @@ -1792,13 +1794,13 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->defrange_subfield_register_v3.reg, sym->defrange_subfield_register_v3.attr, sym->defrange_subfield_register_v3.offParent); - dump_defrange(&sym->defrange_subfield_register_v3.range, get_last(sym), "\t\t"); + dump_defrange(&sym->defrange_subfield_register_v3.range, get_last(sym), indent); break; case S_DEFRANGE_REGISTER_REL: printf("DefRange-register-rel V3 reg:%x off-parent:%x off-BP:%x\n", sym->defrange_registerrel_v3.baseReg, sym->defrange_registerrel_v3.offsetParent, sym->defrange_registerrel_v3.offBasePointer); - dump_defrange(&sym->defrange_registerrel_v3.range, get_last(sym), "\t\t"); + dump_defrange(&sym->defrange_registerrel_v3.range, get_last(sym), indent); break;
case S_CALLSITEINFO: @@ -1813,13 +1815,13 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long case S_INLINESITE: printf("Inline-site V3 parent:%x end:%x inlinee:%x\n", sym->inline_site_v3.pParent, sym->inline_site_v3.pEnd, sym->inline_site_v3.inlinee); - dump_binannot(sym->inline_site_v3.binaryAnnotations, get_last(sym), "\t\t"); + dump_binannot(sym->inline_site_v3.binaryAnnotations, get_last(sym), indent); break; case S_INLINESITE2: printf("Inline-site2 V3 parent:%x end:%x inlinee:%x #inv:%u\n", sym->inline_site2_v3.pParent, sym->inline_site2_v3.pEnd, sym->inline_site2_v3.inlinee, sym->inline_site2_v3.invocations); - dump_binannot(sym->inline_site2_v3.binaryAnnotations, get_last(sym), "\t\t"); + dump_binannot(sym->inline_site2_v3.binaryAnnotations, get_last(sym), indent); break; case S_INLINESITE_END: printf("Inline-site-end\n"); @@ -1841,7 +1843,7 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long ninvoc = (const unsigned*)get_last(sym) - invoc;
for (i = 0; i < sym->function_list_v3.count; ++i) - printf("\t\tfunc:%x invoc:%u\n", sym->function_list_v3.funcs[i], i < ninvoc ? invoc[i] : 0); + printf("%*s| func:%x invoc:%u\n", indent, "", sym->function_list_v3.funcs[i], i < ninvoc ? invoc[i] : 0); } break;
@@ -1883,7 +1885,7 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long const char* ptr = sym->annotation_v3.rgsz; const char* last = ptr + sym->annotation_v3.csz; for (; ptr < last; ptr += strlen(ptr) + 1) - printf("\t%s\n", ptr); + printf("%*s| %s\n", indent, "", ptr); } break;
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- tools/winedump/msc.c | 142 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 101 insertions(+), 41 deletions(-)
diff --git a/tools/winedump/msc.c b/tools/winedump/msc.c index 07691e5be6a..b566018ac89 100644 --- a/tools/winedump/msc.c +++ b/tools/winedump/msc.c @@ -1303,11 +1303,61 @@ static void dump_binannot(const unsigned char* ba, const char* last, unsigned in } }
+struct symbol_dumper +{ + unsigned depth; + unsigned alloc; + struct + { + unsigned end; + const union codeview_symbol* sym; + }* stack; +}; + +static void init_symbol_dumper(struct symbol_dumper* sd) +{ + sd->depth = 0; + sd->alloc = 16; + sd->stack = malloc(sd->alloc * sizeof(sd->stack[0])); +} + +static void push_symbol_dumper(struct symbol_dumper* sd, const union codeview_symbol* sym, unsigned end) +{ + if (!sd->stack) return; + if (sd->depth >= sd->alloc && + !(sd->stack = realloc(sd->stack, (sd->alloc *= 2) * sizeof(sd->stack[0])))) + return; + sd->stack[sd->depth].end = end; + sd->stack[sd->depth].sym = sym; + sd->depth++; +} + +static unsigned short pop_symbol_dumper(struct symbol_dumper* sd, unsigned end) +{ + if (!sd->stack) return 0; + if (!sd->depth) + { + printf(">>> Error in stack\n"); + return 0; + } + sd->depth--; + if (sd->stack[sd->depth].end != end) + printf(">>> Wrong end reference\n"); + return sd->stack[sd->depth].sym->generic.id; +} + +static void dispose_symbol_dumper(struct symbol_dumper* sd) +{ + free(sd->stack); +} + BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long size) { unsigned int i; int length; - int nest_block = 0; + struct symbol_dumper sd; + + init_symbol_dumper(&sd); /* * Loop over the different types of records and whenever we * find something we are interested in, record it and move on. @@ -1315,12 +1365,23 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long for (i = start; i < size; i += length) { const union codeview_symbol* sym = (const union codeview_symbol*)((const char*)root + i); - unsigned indent; + unsigned indent, ref;
length = sym->generic.len + 2; if (!sym->generic.id || length < 4) break; indent = printf(" %04x => ", i);
+ switch (sym->generic.id) + { + case S_END: + case S_INLINESITE_END: + indent += printf("%*s", 2 * sd.depth - 2, ""); + break; + default: + indent += printf("%*s", 2 * sd.depth, ""); + break; + } + switch (sym->generic.id) { /* @@ -1386,6 +1447,7 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long p_string(&sym->thunk_v1.p_name), sym->thunk_v1.segment, sym->thunk_v1.offset, sym->thunk_v1.thunk_len, sym->thunk_v1.thtype); + push_symbol_dumper(&sd, sym, sym->thunk_v1.pend); break;
case S_THUNK32: @@ -1393,47 +1455,38 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->thunk_v3.name, sym->thunk_v3.segment, sym->thunk_v3.offset, sym->thunk_v3.thunk_len, sym->thunk_v3.thtype); + push_symbol_dumper(&sd, sym, sym->thunk_v3.pend); break;
/* Global and static functions */ case S_GPROC32_16t: case S_LPROC32_16t: printf("%s-Proc V1: '%s' (%04x:%08x#%x) type:%x attr:%x\n", - sym->generic.id == S_GPROC32_16t ? "Global" : "-Local", + sym->generic.id == S_GPROC32_16t ? "Global" : "Local", p_string(&sym->proc_v1.p_name), sym->proc_v1.segment, sym->proc_v1.offset, sym->proc_v1.proc_len, sym->proc_v1.proctype, sym->proc_v1.flags); printf("%*s\- Debug: start=%08x end=%08x\n", indent, "", sym->proc_v1.debug_start, sym->proc_v1.debug_end); - if (nest_block) - { - printf(">>> prev func still has nest_block %u count\n", nest_block); - nest_block = 0; - } -/* EPP unsigned int pparent; */ -/* EPP unsigned int pend; */ -/* EPP unsigned int next; */ + printf("%*s\- parent:<%x> end:<%x> next<%x>\n", + indent, "", sym->proc_v1.pparent, sym->proc_v1.pend, sym->proc_v1.next); + push_symbol_dumper(&sd, sym, sym->proc_v1.pend); break;
case S_GPROC32_ST: case S_LPROC32_ST: printf("%s-Proc V2: '%s' (%04x:%08x#%x) type:%x attr:%x\n", - sym->generic.id == S_GPROC32_ST ? "Global" : "-Local", + sym->generic.id == S_GPROC32_ST ? "Global" : "Local", p_string(&sym->proc_v2.p_name), sym->proc_v2.segment, sym->proc_v2.offset, sym->proc_v2.proc_len, sym->proc_v2.proctype, sym->proc_v2.flags); printf("%*s\- Debug: start=%08x end=%08x\n", indent, "", sym->proc_v2.debug_start, sym->proc_v2.debug_end); - if (nest_block) - { - printf(">>> prev func still has nest_block %u count\n", nest_block); - nest_block = 0; - } -/* EPP unsigned int pparent; */ -/* EPP unsigned int pend; */ -/* EPP unsigned int next; */ + printf("%*s\- parent:<%x> end:<%x> next<%x>\n", + indent, "", sym->proc_v2.pparent, sym->proc_v2.pend, sym->proc_v2.next); + push_symbol_dumper(&sd, sym, sym->proc_v2.pend); break;
case S_LPROC32: @@ -1446,14 +1499,9 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long sym->proc_v3.flags); printf("%*s\- Debug: start=%08x end=%08x\n", indent, "", sym->proc_v3.debug_start, sym->proc_v3.debug_end); - if (nest_block) - { - printf(">>> prev func still has nest_block %u count\n", nest_block); - nest_block = 0; - } -/* EPP unsigned int pparent; */ -/* EPP unsigned int pend; */ -/* EPP unsigned int next; */ + printf("%*s\- parent:<%x> end:<%x> next<%x>\n", + indent, "", sym->proc_v3.pparent, sym->proc_v3.pend, sym->proc_v3.next); + push_symbol_dumper(&sd, sym, sym->proc_v3.pend); break;
/* Function parameters and stack variables */ @@ -1503,15 +1551,15 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long p_string(&sym->block_v1.p_name), sym->block_v1.segment, sym->block_v1.offset, sym->block_v1.length); - nest_block++; + push_symbol_dumper(&sd, sym, sym->block_v1.end); break;
case S_BLOCK32: - printf("Block V3 '%s' (%04x:%08x#%08x) parent:%u end:%x\n", + printf("Block V3 '%s' (%04x:%08x#%08x) parent:<%u> end:<%x>\n", sym->block_v3.name, sym->block_v3.segment, sym->block_v3.offset, sym->block_v3.length, sym->block_v3.parent, sym->block_v3.end); - nest_block++; + push_symbol_dumper(&sd, sym, sym->block_v3.end); break;
/* Additional function information */ @@ -1532,13 +1580,17 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long break;
case S_END: - if (nest_block) + ref = sd.depth ? (const char*)sd.stack[sd.depth - 1].sym - (const char*)root : 0; + switch (pop_symbol_dumper(&sd, i)) { - nest_block--; - printf("End-Of block (%u)\n", nest_block); + case S_BLOCK32_ST: + case S_BLOCK32: + printf("End-Of block <%x>\n", ref); + break; + default: + printf("End-Of <%x>\n", ref); + break; } - else - printf("End-Of function\n"); break;
case S_COMPILE: @@ -1813,18 +1865,24 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long break;
case S_INLINESITE: - printf("Inline-site V3 parent:%x end:%x inlinee:%x\n", + printf("Inline-site V3 parent:<%x> end:<%x> inlinee:%x\n", sym->inline_site_v3.pParent, sym->inline_site_v3.pEnd, sym->inline_site_v3.inlinee); dump_binannot(sym->inline_site_v3.binaryAnnotations, get_last(sym), indent); + push_symbol_dumper(&sd, sym, sym->inline_site_v3.pEnd); break; + case S_INLINESITE2: - printf("Inline-site2 V3 parent:%x end:%x inlinee:%x #inv:%u\n", + printf("Inline-site2 V3 parent:<%x> end:<%x> inlinee:%x #inv:%u\n", sym->inline_site2_v3.pParent, sym->inline_site2_v3.pEnd, sym->inline_site2_v3.inlinee, sym->inline_site2_v3.invocations); dump_binannot(sym->inline_site2_v3.binaryAnnotations, get_last(sym), indent); + push_symbol_dumper(&sd, sym, sym->inline_site2_v3.pEnd); break; + case S_INLINESITE_END: - printf("Inline-site-end\n"); + ref = sd.depth ? (const char*)sd.stack[sd.depth - 1].sym - (const char*)root : 0; + pop_symbol_dumper(&sd, i); + printf("Inline-site-end <%x>\n", ref); break;
case S_CALLEES: @@ -1843,7 +1901,8 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long ninvoc = (const unsigned*)get_last(sym) - invoc;
for (i = 0; i < sym->function_list_v3.count; ++i) - printf("%*s| func:%x invoc:%u\n", indent, "", sym->function_list_v3.funcs[i], i < ninvoc ? invoc[i] : 0); + printf("%*s| func:%x invoc:%u\n", + indent, "", sym->function_list_v3.funcs[i], i < ninvoc ? invoc[i] : 0); } break;
@@ -1872,7 +1931,7 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long break;
case S_SEPCODE: - printf("SepCode V3 pParent:%x pEnd:%x separated:%04x:%08x (#%u) from %04x:%08x\n", + printf("SepCode V3 parent:<%x> end:<%x> separated:%04x:%08x (#%u) from %04x:%08x\n", sym->sepcode_v3.pParent, sym->sepcode_v3.pEnd, sym->sepcode_v3.sect, sym->sepcode_v3.off, sym->sepcode_v3.length, sym->sepcode_v3.sectParent, sym->sepcode_v3.offParent); @@ -1894,6 +1953,7 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long dump_data((const void*)sym, sym->generic.len + 2, " "); } } + dispose_symbol_dumper(&sd); return TRUE; }
use it to reimplement dwarf2_feed_inlined_ranges
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 61 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 21 deletions(-)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 90452d74eaf..573c56627a7 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -1272,32 +1272,40 @@ static BOOL dwarf2_read_range(dwarf2_parse_context_t* ctx, const dwarf2_debug_in } }
-static BOOL dwarf2_feed_inlined_ranges(dwarf2_parse_context_t* ctx, const dwarf2_debug_info_t* di, - struct symt_inlinesite* inlined) +static struct addr_range* dwarf2_get_ranges(const dwarf2_debug_info_t* di, unsigned* num_ranges) { struct attribute range; + struct addr_range* ranges;
if (dwarf2_find_attribute(di, DW_AT_ranges, &range)) { dwarf2_traverse_context_t traverse; + unsigned alloc = 16; + ranges = malloc(sizeof(struct addr_range) * alloc); + if (!ranges) return NULL; + *num_ranges = 0;
- traverse.data = ctx->module_ctx->sections[section_ranges].address + range.u.uvalue; - traverse.end_data = ctx->module_ctx->sections[section_ranges].address + - ctx->module_ctx->sections[section_ranges].size; + traverse.data = di->unit_ctx->module_ctx->sections[section_ranges].address + range.u.uvalue; + traverse.end_data = di->unit_ctx->module_ctx->sections[section_ranges].address + + di->unit_ctx->module_ctx->sections[section_ranges].size;
- while (traverse.data + 2 * ctx->head.word_size < traverse.end_data) + while (traverse.data + 2 * di->unit_ctx->head.word_size < traverse.end_data) { - ULONG_PTR low = dwarf2_parse_addr_head(&traverse, &ctx->head); - ULONG_PTR high = dwarf2_parse_addr_head(&traverse, &ctx->head); + ULONG_PTR low = dwarf2_parse_addr_head(&traverse, &di->unit_ctx->head); + ULONG_PTR high = dwarf2_parse_addr_head(&traverse, &di->unit_ctx->head); if (low == 0 && high == 0) break; - if (low == (ctx->head.word_size == 8 ? (~(DWORD64)0u) : (DWORD64)(~0u))) + if (low == (di->unit_ctx->head.word_size == 8 ? (~(DWORD64)0u) : (DWORD64)(~0u))) FIXME("unsupported yet (base address selection)\n"); - /* range values are relative to start of compilation unit */ - symt_add_inlinesite_range(ctx->module_ctx->module, inlined, - ctx->compiland->address + low, ctx->compiland->address + high); + if (*num_ranges >= alloc) + { + alloc *= 2; + ranges = realloc(ranges, sizeof(struct addr_range) * alloc); + if (!ranges) return NULL; + } + ranges[*num_ranges].low = di->unit_ctx->compiland->address + low; + ranges[*num_ranges].high = di->unit_ctx->compiland->address + high; + (*num_ranges)++; } - - return TRUE; } else { @@ -1306,8 +1314,8 @@ static BOOL dwarf2_feed_inlined_ranges(dwarf2_parse_context_t* ctx, const dwarf2
if (!dwarf2_find_attribute(di, DW_AT_low_pc, &low_pc) || !dwarf2_find_attribute(di, DW_AT_high_pc, &high_pc)) - return FALSE; - if (ctx->head.version >= 4) + return NULL; + if (di->unit_ctx->head.version >= 4) switch (high_pc.form) { case DW_FORM_addr: @@ -1325,11 +1333,13 @@ static BOOL dwarf2_feed_inlined_ranges(dwarf2_parse_context_t* ctx, const dwarf2 FIXME("Unsupported class for high_pc\n"); break; } - symt_add_inlinesite_range(ctx->module_ctx->module, inlined, - ctx->module_ctx->load_offset + low_pc.u.uvalue, - ctx->module_ctx->load_offset + high_pc.u.uvalue); - return TRUE; + ranges = malloc(sizeof(struct addr_range)); + if (!ranges) return NULL; + ranges[0].low = di->unit_ctx->module_ctx->load_offset + low_pc.u.uvalue; + ranges[0].high = di->unit_ctx->module_ctx->load_offset + high_pc.u.uvalue; + *num_ranges = 1; } + return ranges; }
/****************************************************************** @@ -2072,6 +2082,8 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm, struct vector* children; dwarf2_debug_info_t*child; unsigned int i; + struct addr_range* adranges; + unsigned num_adranges;
TRACE("%s\n", dwarf2_debug_di(di));
@@ -2099,7 +2111,14 @@ static void dwarf2_parse_inlined_subroutine(dwarf2_subprogram_t* subpgm, subpgm->current_func = (struct symt_function*)inlined; subpgm->current_block = NULL;
- if (!dwarf2_feed_inlined_ranges(subpgm->ctx, di, inlined)) + if ((adranges = dwarf2_get_ranges(di, &num_adranges)) != NULL) + { + for (i = 0; i < num_adranges; ++i) + symt_add_inlinesite_range(subpgm->ctx->module_ctx->module, inlined, + adranges[i].low, adranges[i].high); + free(adranges); + } + else WARN("cannot read ranges\n");
children = dwarf2_get_di_children(di);
gcc can emit functions with code spread across non contiguous code areas We used to register those functions with an address range enclosing all ranges (meaning that all addresses not actually belonging to the function but lying in that address range could be returned by dbghelp as belonging to the function)
Work around this by registering the function with only the first range of addresses (this will avoid the errors described above), but will fail to mark the other address ranges as part of the function.
dbghelp doesn't seem to have explicit support of those cases, even if pdb/codeview also support functions with multi range of addresses (see S_SEPCODE)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dwarf.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/dlls/dbghelp/dwarf.c b/dlls/dbghelp/dwarf.c index 573c56627a7..ef17f7d539f 100644 --- a/dlls/dbghelp/dwarf.c +++ b/dlls/dbghelp/dwarf.c @@ -2239,7 +2239,8 @@ static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm, static struct symt* dwarf2_parse_subprogram(dwarf2_debug_info_t* di) { struct attribute name; - ULONG_PTR low_pc, high_pc; + struct addr_range* addr_ranges; + unsigned num_addr_ranges; struct attribute is_decl; struct attribute inline_flags; struct symt* ret_type; @@ -2276,7 +2277,7 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_debug_info_t* di) /* it's a real declaration, skip it */ return NULL; } - if (!dwarf2_read_range(di->unit_ctx, di, &low_pc, &high_pc)) + if ((addr_ranges = dwarf2_get_ranges(di, &num_addr_ranges)) == NULL) { WARN("cannot get range for %s\n", debugstr_a(name.u.string)); return NULL; @@ -2285,7 +2286,7 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_debug_info_t* di) * (not the case for stabs), we just drop Wine's thunks here... * Actual thunks will be created in elf_module from the symbol table */ - if (elf_is_in_thunk_area(di->unit_ctx->module_ctx->load_offset + low_pc, di->unit_ctx->module_ctx->thunks) >= 0) + if (elf_is_in_thunk_area(di->unit_ctx->module_ctx->load_offset + addr_ranges[0].low, di->unit_ctx->module_ctx->thunks) >= 0) return NULL; ret_type = dwarf2_lookup_type(di);
@@ -2293,8 +2294,11 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_debug_info_t* di) sig_type = symt_new_function_signature(di->unit_ctx->module_ctx->module, ret_type, CV_CALL_FAR_C); subpgm.top_func = symt_new_function(di->unit_ctx->module_ctx->module, di->unit_ctx->compiland, dwarf2_get_cpp_name(di, name.u.string), - di->unit_ctx->module_ctx->load_offset + low_pc, high_pc - low_pc, - &sig_type->symt); + addr_ranges[0].low, addr_ranges[0].high - addr_ranges[0].low, &sig_type->symt); + if (num_addr_ranges > 1) + WARN("Function %s has multiple address ranges, only using the first one\n", name.u.string); + free(addr_ranges); + subpgm.current_func = subpgm.top_func; di->symt = &subpgm.top_func->symt; subpgm.ctx = di->unit_ctx;