The `-fms-hotpatch` flag has been available in Clang since version 14, but it was broken before version 18 (e.g., it could crash on some files when using CI’s Clang). Unfortunately, I couldn’t find a reliable way to check for this in configure, hence the convoluted workaround.
The flag is supported on both 32-bit and 64-bit x86 architectures. It ensures that the first instruction of a function is at least 2 bytes long at the compiler level and adds additional padding during linking.
However, there is a limitation: when the compiler emits multiple functions in a single `.text` section, those functions are not padded. This differs from MSVC, where the compiler handles such padding. Using `-ffunction-sections` mitigates this issue.
While we could limit the use of `-ffunction-sections` to specific cases, it appears beneficial overall. It allows the linker to GC unused functions, which is helpful when linking against static libraries that include both used and unused functions in the same file. This is already the default on ARM64EC, so it makes things more consistent across targets.
From: Jacek Caban jacek@codeweavers.com
--- configure.ac | 1 + 1 file changed, 1 insertion(+)
diff --git a/configure.ac b/configure.ac index 8edfce44d6e..d82e338ae2b 100644 --- a/configure.ac +++ b/configure.ac @@ -961,6 +961,7 @@ This is an error since --enable-archs=$wine_arch was requested.])]) WINE_TRY_PE_CFLAGS([-Wlogical-op]) WINE_TRY_PE_CFLAGS([-Wabsolute-value]) WINE_TRY_PE_CFLAGS([-Wenum-enum-conversion],[:],WINE_TRY_PE_CFLAGS([-Wenum-conversion])) + WINE_TRY_PE_CFLAGS([-ffunction-sections])
dnl GCC can't handle large files when -Wmisleading-indentation is enabled (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89549) WINE_TRY_PE_CFLAGS([-flarge-source-files -Wmisleading-indentation],[AS_VAR_APPEND(${wine_arch}_EXTRACFLAGS,[" -Wno-misleading-indentation"])])
From: Jacek Caban jacek@codeweavers.com
The -fms-hotpatch flag is relevant for both the compiler and the linker. --- tools/winegcc/winegcc.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c index 4fa31cc8a68..60cc6148158 100644 --- a/tools/winegcc/winegcc.c +++ b/tools/winegcc/winegcc.c @@ -1641,6 +1641,8 @@ int main(int argc, char **argv) opts.unwind_tables = 1; else if (!strcmp("-fno-asynchronous-unwind-tables", opts.args.str[i])) opts.unwind_tables = 0; + else if (!strcmp("-fms-hotpatch", opts.args.str[i])) + raw_linker_arg = 1; else if (!strcmp("-fPIC", opts.args.str[i]) || !strcmp("-fpic", opts.args.str[i])) opts.pic = 1; else if (!strcmp("-fno-PIC", opts.args.str[i]) || !strcmp("-fno-pic", opts.args.str[i]))
From: Jacek Caban jacek@codeweavers.com
On Clang, this flag serves as a replacement for the __ms_hook_prologue__ attribute. --- aclocal.m4 | 3 +++ configure.ac | 5 +++++ 2 files changed, 8 insertions(+)
diff --git a/aclocal.m4 b/aclocal.m4 index b319e283209..9efbd7ebb3e 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -198,6 +198,9 @@ ac_wine_try_cflags_saved_exeext=$ac_exeext CFLAGS="$CFLAGS -nostdlib -nodefaultlibs $1" ac_exeext=".exe" AC_LINK_IFELSE([AC_LANG_SOURCE([[void *__os_arm64x_dispatch_ret = 0; +#if defined(__clang_major__) && defined(MIN_CLANG_VERSION) && __clang_major__ < MIN_CLANG_VERSION +#error Too old clang version +#endif int __cdecl mainCRTStartup(void) { return 0; }]])], [AS_VAR_SET(ac_var,yes)], [AS_VAR_SET(ac_var,no)]) CFLAGS=$ac_wine_try_cflags_saved diff --git a/configure.ac b/configure.ac index d82e338ae2b..94260d7ae7b 100644 --- a/configure.ac +++ b/configure.ac @@ -963,6 +963,11 @@ This is an error since --enable-archs=$wine_arch was requested.])]) WINE_TRY_PE_CFLAGS([-Wenum-enum-conversion],[:],WINE_TRY_PE_CFLAGS([-Wenum-conversion])) WINE_TRY_PE_CFLAGS([-ffunction-sections])
+ dnl clang had broken -fms-hotpatch support before version 18 (https://github.com/llvm/llvm-project/pull/77245) + WINE_TRY_PE_CFLAGS([-fms-hotpatch -DMIN_CLANG_VERSION=18], + [AS_VAR_APPEND([${wine_arch}_EXTRACFLAGS],[" -fms-hotpatch"]) + AS_VAR_APPEND([${wine_arch}_LDFLAGS],[" -fms-hotpatch"])]) + dnl GCC can't handle large files when -Wmisleading-indentation is enabled (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89549) WINE_TRY_PE_CFLAGS([-flarge-source-files -Wmisleading-indentation],[AS_VAR_APPEND(${wine_arch}_EXTRACFLAGS,[" -Wno-misleading-indentation"])])