From 8de547d3e6b22a6f5738116d903ce25e6be2d7eb Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Wed, 10 Nov 2021 16:43:36 +0100 Subject: [PATCH] winedump: Better handle display of nested symbol entries. Signed-off-by: Eric Pouech Signed-off-by: Alexandre Julliard --- 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; }