[PATCH 08/10] tools/winedump: better handling and display of nested symbol entries
Eric Pouech
eric.pouech at gmail.com
Wed Nov 10 09:43:36 CST 2021
Signed-off-by: Eric Pouech <eric.pouech at 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;
}
More information about the wine-devel
mailing list