Module: wine Branch: master Commit: aa256deedd02662d72ad563e9d29d16714543bb3 URL: https://source.winehq.org/git/wine.git/?a=commit;h=aa256deedd02662d72ad563e9...
Author: Martin Storsjö martin@martin.st Date: Tue Nov 9 16:05:47 2021 +0200
winedump: Rewrite dumping of packed ARM unwind info.
This differs slightly from the official docs (which is clear in some places, vague in others, and contradictory in some places), based on actual observed behaviour.
Signed-off-by: Martin Storsjö martin@martin.st Signed-off-by: Alexandre Julliard julliard@winehq.org
---
tools/winedump/pe.c | 146 +++++++++++++++++++++------------------------------- 1 file changed, 58 insertions(+), 88 deletions(-)
diff --git a/tools/winedump/pe.c b/tools/winedump/pe.c index 43ba0618615..6ff14f95791 100644 --- a/tools/winedump/pe.c +++ b/tools/winedump/pe.c @@ -787,7 +787,7 @@ static void dump_armnt_unwind_info( const struct runtime_function_armnt *fnc ) if (fnc->u.s.Flag) { char intregs[32] = {0}, intregspop[32] = {0}, vfpregs[32] = {0}; - WORD pf = 0, ef = 0, sc = 0; + WORD pf = 0, ef = 0, fpoffset = 0, stack = fnc->u.s.StackAdjust;
printf( "\nFunction %08x-%08x:\n", fnc->BeginAddress & ~1, (fnc->BeginAddress & ~1) + fnc->u.s.FunctionLength * 2 ); @@ -805,86 +805,60 @@ static void dump_armnt_unwind_info( const struct runtime_function_armnt *fnc ) { pf = fnc->u.s.StackAdjust & 0x04; ef = fnc->u.s.StackAdjust & 0x08; + stack = (fnc->u.s.StackAdjust & 3) + 1; }
- if (!fnc->u.s.R && !pf) + if (!fnc->u.s.R || pf) { - if (fnc->u.s.Reg) + int first = 4, last = fnc->u.s.Reg + 4; + if (pf) { - sprintf(intregs, "r4-r%u", fnc->u.s.Reg + 4); - sprintf(intregspop, "r4-r%u", fnc->u.s.Reg + 4); + first = (~fnc->u.s.StackAdjust) & 3; + if (fnc->u.s.R) + last = 3; } + if (first == last) + sprintf(intregs, "r%u", first); else - { - strcpy(intregs, "r4"); - strcpy(intregspop, "r4"); - } - sc = fnc->u.s.Reg + 1; - if (fnc->u.s.C || fnc->u.s.L) - { - strcat(intregs, ", "); - if (fnc->u.s.C || (fnc->u.s.L && !fnc->u.s.H)) - strcat(intregspop, ", "); - } + sprintf(intregs, "r%u-r%u", first, last); + fpoffset = last + 1 - first; } - else if (fnc->u.s.R && pf) + + if (!fnc->u.s.R || ef) { - if (((~fnc->u.s.StackAdjust) & 3) != 3) + int first = 4, last = fnc->u.s.Reg + 4; + if (ef) { - sprintf(intregs, "r%u-r3", (~fnc->u.s.StackAdjust) & 3); - sprintf(intregspop, "r%u-r3", (~fnc->u.s.StackAdjust) & 3); + first = (~fnc->u.s.StackAdjust) & 3; + if (fnc->u.s.R) + last = 3; } + if (first == last) + sprintf(intregspop, "r%u", first); else - { - sprintf(intregs, "r3"); - sprintf(intregspop, "r3"); - } - sc = 4 - ((~fnc->u.s.StackAdjust) & 3); - if (fnc->u.s.C || fnc->u.s.L) - { - strcat(intregs, ", "); - if (fnc->u.s.C || (fnc->u.s.L && !fnc->u.s.H)) - strcat(intregspop, ", "); - } - } - else if (!fnc->u.s.R && pf) - { - sprintf(intregs, "r%u-r%u", (~fnc->u.s.StackAdjust) & 3, fnc->u.s.Reg + 4); - sprintf(intregspop, "r%u-r%u", (~fnc->u.s.StackAdjust) & 3, fnc->u.s.Reg + 4); - sc = fnc->u.s.Reg + 5 - ((~fnc->u.s.StackAdjust) & 3); - if (fnc->u.s.C || fnc->u.s.L) - { - strcat(intregs, ", "); - if (fnc->u.s.C || (fnc->u.s.L && !fnc->u.s.H)) - strcat(intregspop, ", "); - } - } - else if (fnc->u.s.R && !pf) - { - if (!fnc->u.s.C && !fnc->u.s.L) - { - strcpy(intregs, "none"); - strcpy(intregspop, "none"); - } + sprintf(intregspop, "r%u-r%u", first, last); }
- if (fnc->u.s.C && !fnc->u.s.L) + if (fnc->u.s.C) { + if (intregs[0]) + strcat(intregs, ", "); + if (intregspop[0]) + strcat(intregspop, ", "); strcat(intregs, "r11"); strcat(intregspop, "r11"); } - else if (fnc->u.s.C && fnc->u.s.L) - { - strcat(intregs, "r11, lr"); - if (fnc->u.s.H) - strcat(intregspop, "r11"); - else - strcat(intregspop, "r11, pc"); - } - else if (!fnc->u.s.C && fnc->u.s.L) + if (fnc->u.s.L) { + if (intregs[0]) + strcat(intregs, ", "); strcat(intregs, "lr"); - if (!fnc->u.s.H) + + if (intregspop[0] && (fnc->u.s.Ret != 0 || !fnc->u.s.H)) + strcat(intregspop, ", "); + if (fnc->u.s.Ret != 0) + strcat(intregspop, "lr"); + else if (!fnc->u.s.H) strcat(intregspop, "pc"); }
@@ -895,46 +869,42 @@ static void dump_armnt_unwind_info( const struct runtime_function_armnt *fnc ) else strcpy(vfpregs, "d8"); } - else - strcpy(vfpregs, "none");
- if (fnc->u.s.H) - printf( " Unwind Code\tpush {r0-r3}\n" ); + if (fnc->u.s.Flag == 1) { + if (fnc->u.s.H) + printf( " Unwind Code\tpush {r0-r3}\n" );
- if (fnc->u.s.R || fnc->u.s.L || fnc->u.s.C || pf) - printf( " Unwind Code\tpush {%s}\n", intregs ); + if (intregs[0]) + printf( " Unwind Code\tpush {%s}\n", intregs );
- if (fnc->u.s.C && fnc->u.s.R && !fnc->u.s.L && !pf) - printf( " Unwind Code\tmov r11, sp\n" ); - else if (fnc->u.s.C && (!fnc->u.s.R || fnc->u.s.L || pf)) - { - if (fnc->u.s.StackAdjust >= 0x03f4 && !sc) - printf( " Unwind Code\tadd r11, sp, #<unknown>\n"); - else if (fnc->u.s.StackAdjust >= 0x03f4) - printf( " Unwind Code\tadd r11, sp, #%d\n", sc * 4 ); - else - printf( " Unwind Code\tadd r11, sp, #%d\n", fnc->u.s.StackAdjust * 4 ); - } + if (fnc->u.s.C && fpoffset == 0) + printf( " Unwind Code\tmov r11, sp\n" ); + else if (fnc->u.s.C) + printf( " Unwind Code\tadd r11, sp, #%d\n", fpoffset * 4 );
- if (fnc->u.s.R && fnc->u.s.Reg != 0x07) - printf( " Unwind Code\tvpush {%s}\n", vfpregs ); + if (fnc->u.s.R && fnc->u.s.Reg != 0x07) + printf( " Unwind Code\tvpush {%s}\n", vfpregs );
- if (fnc->u.s.StackAdjust < 0x03f4 && !pf) - printf( " Unwind Code\tsub sp, sp, #%d\n", fnc->u.s.StackAdjust * 4 ); + if (stack && !pf) + printf( " Unwind Code\tsub sp, sp, #%d\n", stack * 4 ); + }
+ if (fnc->u.s.Ret == 3) + return; + printf( "Epilogue:\n" );
- if (fnc->u.s.StackAdjust < 0x03f4 && !ef) - printf( " Unwind Code\tadd sp, sp, #%d\n", fnc->u.s.StackAdjust * 4 ); + if (stack && !ef) + printf( " Unwind Code\tadd sp, sp, #%d\n", stack * 4 );
if (fnc->u.s.R && fnc->u.s.Reg != 0x07) printf( " Unwind Code\tvpop {%s}\n", vfpregs );
- if (fnc->u.s.C || !fnc->u.s.R || ef || (fnc->u.s.L && !fnc->u.s.H)) + if (intregspop[0]) printf( " Unwind Code\tpop {%s}\n", intregspop );
- if (fnc->u.s.H && !fnc->u.s.L) + if (fnc->u.s.H && !(fnc->u.s.L && fnc->u.s.Ret == 0)) printf( " Unwind Code\tadd sp, sp, #16\n" ); - else if (fnc->u.s.H && fnc->u.s.L) + else if (fnc->u.s.H && (fnc->u.s.L && fnc->u.s.Ret == 0)) printf( " Unwind Code\tldr pc, [sp], #20\n" );
if (fnc->u.s.Ret == 1)