Force as to emit expected CIE/FDE information for x86_64 CPU in .debug_frame section.
This has been unveiled by 425bd55b02e375b9ac8f79b254ce3ca5c9e72719 (before this commit, the .cfi directives where not emitted by winebuild).
x86_64-w64-mingw32-as on x86_64 emits "strange" unwinding information (from winebuild).
00000000 0000000000000014 ffffffff CIE Version: 1 Augmentation: "" Code alignment factor: 1 Data alignment factor: -8 Return address column: 32
DW_CFA_def_cfa: r7 (rsp) ofs 8 DW_CFA_offset: r32 (xmm15) at cfa-8 DW_CFA_nop DW_CFA_nop DW_CFA_nop DW_CFA_nop DW_CFA_nop DW_CFA_nop
Consequence: in unwinding, xmm15 gets updated, but rip isn't, causing an infinite loop in dbghelp.
Wine-Bug-Id: https://bugs.winehq.org/show_bug.cgi?id=55560
Signed-off-by: Eric Pouech epouech@codeweavers.com
-- v2: tools/winebuild: Emit SEH unwind information instead of dwarf.
From: Eric Pouech epouech@codeweavers.com
Done for syscall and import thunks on PE targets.
Wine-Bug-Id: https://bugs.winehq.org/show_bug.cgi?id=55560
Signed-off-by: Eric Pouech epouech@codeweavers.com --- tools/winebuild/build.h | 2 ++ tools/winebuild/import.c | 8 ++++---- tools/winebuild/utils.c | 13 +++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 733cd34e614..dfa8574a5da 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -246,6 +246,8 @@ extern int output( const char *format, ... ) __attribute__ ((__format__ (__printf__, 1, 2))); extern void output_cfi( const char *format, ... ) __attribute__ ((__format__ (__printf__, 1, 2))); +extern void output_seh( const char *format, ... ) + __attribute__ ((__format__ (__printf__, 1, 2))); extern void output_rva( const char *format, ... ) __attribute__ ((__format__ (__printf__, 1, 2))); extern void output_thunk_rva( int ordinal, const char *format, ... ) diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index de4bc26f60d..6d0642fdb28 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -769,7 +769,7 @@ static void output_import_thunk( const char *name, const char *table, int pos ) output( "\n\t.align %d\n", get_alignment(4) ); output( "\t%s\n", func_declaration(name) ); output( "%s\n", asm_globl(name) ); - output_cfi( ".cfi_startproc" ); + output_seh( ".seh_proc %s", asm_name(name) );
switch (target.cpu) { @@ -811,7 +811,7 @@ static void output_import_thunk( const char *name, const char *table, int pos ) output( "\tbr x16\n" ); break; } - output_cfi( ".cfi_endproc" ); + output_seh( ".seh_endproc" ); output_function_size( name ); }
@@ -1421,7 +1421,7 @@ void output_syscalls( DLLSPEC *spec ) output( "\t.align %d\n", get_alignment(16) ); output( "\t%s\n", func_declaration(name) ); output( "%s\n", asm_globl(name) ); - output_cfi( ".cfi_startproc" ); + output_seh( ".seh_proc %s", asm_name(name) ); switch (target.cpu) { case CPU_i386: @@ -1483,7 +1483,7 @@ void output_syscalls( DLLSPEC *spec ) default: assert(0); } - output_cfi( ".cfi_endproc" ); + output_seh( ".seh_endproc" ); output_function_size( name ); }
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index 49d2468b236..41e3462bfb2 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -938,6 +938,19 @@ void output_cfi( const char *format, ... ) va_end( valist ); }
+/* output a .seh directive */ +void output_seh( const char *format, ... ) +{ + va_list valist; + + if (!unwind_tables || target.cpu == CPU_i386) return; + va_start( valist, format ); + fputc( '\t', output_file ); + vfprintf( output_file, format, valist ); + fputc( '\n', output_file ); + va_end( valist ); +} + /* output an RVA pointer */ void output_rva( const char *format, ... ) {