mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-15 05:57:27 +00:00
winedump: Better handle display of nested symbol entries.
Signed-off-by: Eric Pouech <eric.pouech@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2447b0131b
commit
8de547d3e6
|
@ -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)
|
BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int length;
|
int length;
|
||||||
int nest_block = 0;
|
struct symbol_dumper sd;
|
||||||
|
|
||||||
|
init_symbol_dumper(&sd);
|
||||||
/*
|
/*
|
||||||
* Loop over the different types of records and whenever we
|
* Loop over the different types of records and whenever we
|
||||||
* find something we are interested in, record it and move on.
|
* 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)
|
for (i = start; i < size; i += length)
|
||||||
{
|
{
|
||||||
const union codeview_symbol* sym = (const union codeview_symbol*)((const char*)root + i);
|
const union codeview_symbol* sym = (const union codeview_symbol*)((const char*)root + i);
|
||||||
unsigned indent;
|
unsigned indent, ref;
|
||||||
|
|
||||||
length = sym->generic.len + 2;
|
length = sym->generic.len + 2;
|
||||||
if (!sym->generic.id || length < 4) break;
|
if (!sym->generic.id || length < 4) break;
|
||||||
indent = printf(" %04x => ", i);
|
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)
|
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),
|
p_string(&sym->thunk_v1.p_name),
|
||||||
sym->thunk_v1.segment, sym->thunk_v1.offset,
|
sym->thunk_v1.segment, sym->thunk_v1.offset,
|
||||||
sym->thunk_v1.thunk_len, sym->thunk_v1.thtype);
|
sym->thunk_v1.thunk_len, sym->thunk_v1.thtype);
|
||||||
|
push_symbol_dumper(&sd, sym, sym->thunk_v1.pend);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_THUNK32:
|
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.name,
|
||||||
sym->thunk_v3.segment, sym->thunk_v3.offset,
|
sym->thunk_v3.segment, sym->thunk_v3.offset,
|
||||||
sym->thunk_v3.thunk_len, sym->thunk_v3.thtype);
|
sym->thunk_v3.thunk_len, sym->thunk_v3.thtype);
|
||||||
|
push_symbol_dumper(&sd, sym, sym->thunk_v3.pend);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Global and static functions */
|
/* Global and static functions */
|
||||||
case S_GPROC32_16t:
|
case S_GPROC32_16t:
|
||||||
case S_LPROC32_16t:
|
case S_LPROC32_16t:
|
||||||
printf("%s-Proc V1: '%s' (%04x:%08x#%x) type:%x attr:%x\n",
|
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),
|
p_string(&sym->proc_v1.p_name),
|
||||||
sym->proc_v1.segment, sym->proc_v1.offset,
|
sym->proc_v1.segment, sym->proc_v1.offset,
|
||||||
sym->proc_v1.proc_len, sym->proc_v1.proctype,
|
sym->proc_v1.proc_len, sym->proc_v1.proctype,
|
||||||
sym->proc_v1.flags);
|
sym->proc_v1.flags);
|
||||||
printf("%*s\\- Debug: start=%08x end=%08x\n",
|
printf("%*s\\- Debug: start=%08x end=%08x\n",
|
||||||
indent, "", sym->proc_v1.debug_start, sym->proc_v1.debug_end);
|
indent, "", sym->proc_v1.debug_start, sym->proc_v1.debug_end);
|
||||||
if (nest_block)
|
printf("%*s\\- parent:<%x> end:<%x> next<%x>\n",
|
||||||
{
|
indent, "", sym->proc_v1.pparent, sym->proc_v1.pend, sym->proc_v1.next);
|
||||||
printf(">>> prev func still has nest_block %u count\n", nest_block);
|
push_symbol_dumper(&sd, sym, sym->proc_v1.pend);
|
||||||
nest_block = 0;
|
|
||||||
}
|
|
||||||
/* EPP unsigned int pparent; */
|
|
||||||
/* EPP unsigned int pend; */
|
|
||||||
/* EPP unsigned int next; */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_GPROC32_ST:
|
case S_GPROC32_ST:
|
||||||
case S_LPROC32_ST:
|
case S_LPROC32_ST:
|
||||||
printf("%s-Proc V2: '%s' (%04x:%08x#%x) type:%x attr:%x\n",
|
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),
|
p_string(&sym->proc_v2.p_name),
|
||||||
sym->proc_v2.segment, sym->proc_v2.offset,
|
sym->proc_v2.segment, sym->proc_v2.offset,
|
||||||
sym->proc_v2.proc_len, sym->proc_v2.proctype,
|
sym->proc_v2.proc_len, sym->proc_v2.proctype,
|
||||||
sym->proc_v2.flags);
|
sym->proc_v2.flags);
|
||||||
printf("%*s\\- Debug: start=%08x end=%08x\n",
|
printf("%*s\\- Debug: start=%08x end=%08x\n",
|
||||||
indent, "", sym->proc_v2.debug_start, sym->proc_v2.debug_end);
|
indent, "", sym->proc_v2.debug_start, sym->proc_v2.debug_end);
|
||||||
if (nest_block)
|
printf("%*s\\- parent:<%x> end:<%x> next<%x>\n",
|
||||||
{
|
indent, "", sym->proc_v2.pparent, sym->proc_v2.pend, sym->proc_v2.next);
|
||||||
printf(">>> prev func still has nest_block %u count\n", nest_block);
|
push_symbol_dumper(&sd, sym, sym->proc_v2.pend);
|
||||||
nest_block = 0;
|
|
||||||
}
|
|
||||||
/* EPP unsigned int pparent; */
|
|
||||||
/* EPP unsigned int pend; */
|
|
||||||
/* EPP unsigned int next; */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_LPROC32:
|
case S_LPROC32:
|
||||||
|
@ -1446,14 +1499,9 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long
|
||||||
sym->proc_v3.flags);
|
sym->proc_v3.flags);
|
||||||
printf("%*s\\- Debug: start=%08x end=%08x\n",
|
printf("%*s\\- Debug: start=%08x end=%08x\n",
|
||||||
indent, "", sym->proc_v3.debug_start, sym->proc_v3.debug_end);
|
indent, "", sym->proc_v3.debug_start, sym->proc_v3.debug_end);
|
||||||
if (nest_block)
|
printf("%*s\\- parent:<%x> end:<%x> next<%x>\n",
|
||||||
{
|
indent, "", sym->proc_v3.pparent, sym->proc_v3.pend, sym->proc_v3.next);
|
||||||
printf(">>> prev func still has nest_block %u count\n", nest_block);
|
push_symbol_dumper(&sd, sym, sym->proc_v3.pend);
|
||||||
nest_block = 0;
|
|
||||||
}
|
|
||||||
/* EPP unsigned int pparent; */
|
|
||||||
/* EPP unsigned int pend; */
|
|
||||||
/* EPP unsigned int next; */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Function parameters and stack variables */
|
/* 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),
|
p_string(&sym->block_v1.p_name),
|
||||||
sym->block_v1.segment, sym->block_v1.offset,
|
sym->block_v1.segment, sym->block_v1.offset,
|
||||||
sym->block_v1.length);
|
sym->block_v1.length);
|
||||||
nest_block++;
|
push_symbol_dumper(&sd, sym, sym->block_v1.end);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_BLOCK32:
|
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.name,
|
||||||
sym->block_v3.segment, sym->block_v3.offset, sym->block_v3.length,
|
sym->block_v3.segment, sym->block_v3.offset, sym->block_v3.length,
|
||||||
sym->block_v3.parent, sym->block_v3.end);
|
sym->block_v3.parent, sym->block_v3.end);
|
||||||
nest_block++;
|
push_symbol_dumper(&sd, sym, sym->block_v3.end);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Additional function information */
|
/* Additional function information */
|
||||||
|
@ -1532,13 +1580,17 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_END:
|
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--;
|
case S_BLOCK32_ST:
|
||||||
printf("End-Of block (%u)\n", nest_block);
|
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;
|
break;
|
||||||
|
|
||||||
case S_COMPILE:
|
case S_COMPILE:
|
||||||
|
@ -1813,18 +1865,24 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_INLINESITE:
|
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);
|
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);
|
dump_binannot(sym->inline_site_v3.binaryAnnotations, get_last(sym), indent);
|
||||||
|
push_symbol_dumper(&sd, sym, sym->inline_site_v3.pEnd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_INLINESITE2:
|
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.pParent, sym->inline_site2_v3.pEnd, sym->inline_site2_v3.inlinee,
|
||||||
sym->inline_site2_v3.invocations);
|
sym->inline_site2_v3.invocations);
|
||||||
dump_binannot(sym->inline_site2_v3.binaryAnnotations, get_last(sym), indent);
|
dump_binannot(sym->inline_site2_v3.binaryAnnotations, get_last(sym), indent);
|
||||||
|
push_symbol_dumper(&sd, sym, sym->inline_site2_v3.pEnd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_INLINESITE_END:
|
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;
|
break;
|
||||||
|
|
||||||
case S_CALLEES:
|
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;
|
ninvoc = (const unsigned*)get_last(sym) - invoc;
|
||||||
|
|
||||||
for (i = 0; i < sym->function_list_v3.count; ++i)
|
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;
|
break;
|
||||||
|
|
||||||
|
@ -1872,7 +1931,7 @@ BOOL codeview_dump_symbols(const void* root, unsigned long start, unsigned long
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case S_SEPCODE:
|
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.pParent, sym->sepcode_v3.pEnd,
|
||||||
sym->sepcode_v3.sect, sym->sepcode_v3.off, sym->sepcode_v3.length,
|
sym->sepcode_v3.sect, sym->sepcode_v3.off, sym->sepcode_v3.length,
|
||||||
sym->sepcode_v3.sectParent, sym->sepcode_v3.offParent);
|
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, " ");
|
dump_data((const void*)sym, sym->generic.len + 2, " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dispose_symbol_dumper(&sd);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue