diff --git a/.github/workflows/build_test.yml b/.github/workflows/build_test.yml
index 22f94477a..cbd54c9f9 100644
--- a/.github/workflows/build_test.yml
+++ b/.github/workflows/build_test.yml
@@ -84,6 +84,15 @@ jobs:
python_packages: pywin32
mingw_url: https://github.com/niXman/mingw-builds-binaries/releases/download/16.1.0-rt_v14-rev1/x86_64-16.1.0-release-posix-seh-msvcrt-rt_v14-rev1.7z
+ - name: Windows i686 MinGW
+ vm_image: windows-2022
+ sdk_platform: windows-amd64
+ scons_build_args: platform=x86-32 --no-clang mingw=1 werror=1 mingw_dir=mingw/mingw tls_edit_i686=1
+ scons_tests: small_tests medium_tests large_tests disable_tests=run_toolchain_python_tests
+ vpython: pyenv/Scripts/python
+ python_packages: pywin32
+ mingw_url: https://github.com/niXman/mingw-builds-binaries/releases/download/16.1.0-rt_v14-rev1/i686-16.1.0-release-posix-dwarf-msvcrt-rt_v14-rev1.7z
+
# Azure exposed matrix values as environment variables; do the same here
# so the scripts below can stay as plain shell.
env:
@@ -151,4 +160,4 @@ jobs:
run: |
set -xue
parallelism="$(${NPROC_COMMAND:-nproc})"
- ${VPYTHON} -m SCons --mode=opt-host,nacl saigo=1 saigo_newlib_dir=sdk/sdk ${SCONS_BUILD_ARGS} ${SCONS_TESTS} -j${parallelism} --verbose --keep-going disable_flaky_tests=1
+ ${VPYTHON} -m SCons -Q --mode=opt-host,nacl saigo=1 saigo_newlib_dir=sdk/sdk ${SCONS_BUILD_ARGS} ${SCONS_TESTS} -j${parallelism} --verbose --keep-going disable_flaky_tests=1
diff --git a/README.md b/README.md
index e24f101e8..11b847c46 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,8 @@ Target & compiler|Build status|Target & compiler|Build status
Linux amd64 GCC|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)|Windows amd64 MSVC|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)
Linux amd64 Clang|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)|Windows i686 MSVC|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)
Linux i686 GCC|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)|Windows amd64 MinGW|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)
-Linux armhf GCC|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)|macOS amd64 AppleClang|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)
+Linux armhf GCC|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)|Windows i686 MinGW|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)
+macOS amd64 AppleClang|[](https://github.com/DaemonEngine/native_client/actions/workflows/build_test.yml?query=branch%3Amaster)
Native Client (also known as NaCl) is a sandboxing technology by Google.
It was used by Chrome extensions and Chrome apps.
diff --git a/SConstruct b/SConstruct
index 69aaa7939..8cebb70a3 100755
--- a/SConstruct
+++ b/SConstruct
@@ -277,6 +277,9 @@ def SetUpArgumentBits(env):
BitFromArgument(env, 'mingw', default=False,
desc='Use MinGW toolchain for trusted build')
+ BitFromArgument(env, 'tls_edit_i686', default=False,
+ desc='Build tls_edit as an i686 Windows host tool')
+
BitFromArgument(env, 'pnacl_native_clang_driver', default=False,
desc='Use the (experimental) native PNaCl Clang driver')
@@ -2314,6 +2317,9 @@ def MakeWindowsEnv(platform=None):
if windows_env.Bit('mingw'):
# Some C++-using binaries are linked with the C compiler
windows_env.Append(LIBS = ['stdc++'])
+ if windows_env.Bit('build_x86_32'):
+ # Enable SSE2 for x86-32 MinGW builds so SSE intrinsics compile correctly.
+ windows_env.Append(CCFLAGS = ['-msse2'])
else:
# TODO(bsy) remove 4355 once cross-repo
# NACL_ALLOW_THIS_IN_INITIALIZER_LIST changes go in.
@@ -2328,7 +2334,8 @@ def MakeWindowsEnv(platform=None):
# This linker option allows us to ensure our builds are compatible with
# Chromium, which uses it.
if windows_env.Bit('build_x86_32'):
- windows_env.Append(LINKFLAGS = "/safeseh")
+ if not windows_env.Bit('mingw'):
+ windows_env.Append(LINKFLAGS = "/safeseh")
mingw_dir = os.path.abspath(ARGUMENTS.get('mingw_dir', 'You.must.provide.the.mingw_dir.argument'))
windows_env['MINGW_BIN'] = os.path.join(mingw_dir, 'bin')
@@ -3718,6 +3725,15 @@ def LinkTrustedEnv(selected_envs):
def MakeBuildEnv():
build_platform = GetBuildPlatform()
+ tls_edit_i686 = pre_base_env.Bit('tls_edit_i686')
+ if tls_edit_i686:
+ if not pre_base_env.Bit('mingw'):
+ raise UserError('tls_edit_i686 requires mingw=1')
+ if GetTargetPlatform() != 'x86-32':
+ raise UserError(
+ 'tls_edit_i686 requires a 32-bit target (platform=x86-32)')
+ build_platform = 'x86-32'
+
# Build Platform Base Function
platform_func_map = {
'win32' : MakeWindowsEnv,
@@ -3728,10 +3744,21 @@ def MakeBuildEnv():
}
if sys.platform not in platform_func_map:
raise UserError('Unrecognized host platform: %s', sys.platform)
- make_env_func = platform_func_map[sys.platform]
+ # tls_edit_i686 builds a Windows host tool with the i686 MinGW
+ # toolchain, even when SCons itself is running on Linux.
+ if tls_edit_i686:
+ make_env_func = MakeWindowsEnv
+ else:
+ make_env_func = platform_func_map[sys.platform]
build_env = make_env_func(build_platform)
build_env['IS_BUILD_ENV'] = True
+ if tls_edit_i686:
+ build_env.Append(LINKFLAGS=[
+ '-static',
+ '-static-libgcc',
+ '-static-libstdc++',
+ ])
# Building tls_edit depends on gio, platform, and validator_ragel.
build_env['BUILD_SCONSCRIPTS'] = [
diff --git a/src/trusted/platform_qualify/arch/x86/vcpuid.c b/src/trusted/platform_qualify/arch/x86/vcpuid.c
index dbefa9b11..27e5abb32 100644
--- a/src/trusted/platform_qualify/arch/x86/vcpuid.c
+++ b/src/trusted/platform_qualify/arch/x86/vcpuid.c
@@ -38,7 +38,15 @@ const int kMagicConst_ROUNDSS = 0xc0000000;
const int kMagicConst_POPCNT = 13;
const int kMagicConst_CRC32 = 0xb906c3ea;
-#if !(NACL_WINDOWS && (NACL_BUILD_SUBARCH == 64))
+#if (NACL_WINDOWS && defined(_MSC_VER) && (NACL_BUILD_SUBARCH == 64))
+# define NACL_WINDOWS_MSC_64
+#endif
+
+#if (NACL_WINDOWS && !defined(_MSC_VER))
+# define NACL_WINDOWS_MINGW
+#endif
+
+#if !defined(NACL_WINDOWS_MSC_64) && !defined(NACL_WINDOWS_MINGW)
static int asm_HasMMX(void) {
volatile int before, after;
before = kMagicConst;
@@ -386,8 +394,9 @@ static int asm_HasCX8(void) {
#endif /* 0 */
#endif /* 64-bit Windows */
-#if NACL_WINDOWS && (NACL_BUILD_SUBARCH == 64)
+#if defined(NACL_WINDOWS_MSC_64) || defined(NACL_WINDOWS_MINGW)
static int CheckCPUFeatureDetection(NaClCPUFeaturesX86 *cpuf) {
+ (void)cpuf;
/* Unfortunately the asm_ tests will not work on 64-bit Windows */
return 0;
}
diff --git a/src/trusted/service_runtime/arch/x86_32/nacl_switch_to_app_32.c b/src/trusted/service_runtime/arch/x86_32/nacl_switch_to_app_32.c
index 47e4d9d9b..5a5ec20e6 100644
--- a/src/trusted/service_runtime/arch/x86_32/nacl_switch_to_app_32.c
+++ b/src/trusted/service_runtime/arch/x86_32/nacl_switch_to_app_32.c
@@ -71,7 +71,7 @@ NORETURN void NaClStartThreadInApp(struct NaClAppThread *natp,
NaClSwitch(context);
-#if NACL_WINDOWS && defined(__clang__)
+#if NACL_WINDOWS && (defined(__clang__) || defined(__GNUC__))
/*
* NaClSwitch is a function pointer in x86_32 and there's no way to mark
* the function pointed to by a function pointer as noreturn in clang-cl mode.
diff --git a/src/trusted/service_runtime/arch/x86_32/sel_rt_32.h b/src/trusted/service_runtime/arch/x86_32/sel_rt_32.h
index cce501c92..6f260e8f5 100644
--- a/src/trusted/service_runtime/arch/x86_32/sel_rt_32.h
+++ b/src/trusted/service_runtime/arch/x86_32/sel_rt_32.h
@@ -98,9 +98,17 @@ struct NaClGsSegment {
*/
#if NACL_WINDOWS
/* Align gs_segment for better performance on Intel Atom */
-__declspec(align(64))
+#if defined(_MSC_VER)
+#define NACL_THREAD_CONTEXT_ALIGN __declspec(align(64))
+#elif defined(__GNUC__)
+#define NACL_THREAD_CONTEXT_ALIGN __attribute__((aligned(64)))
+#else
+#define NACL_THREAD_CONTEXT_ALIGN
#endif
-struct NaClThreadContext {
+#else
+#define NACL_THREAD_CONTEXT_ALIGN
+#endif
+struct NACL_THREAD_CONTEXT_ALIGN NaClThreadContext {
/*
* We align gs_segment to a multiple of 64 bytes because otherwise
* memory accesses through the %gs segment are slow on Intel Atom
diff --git a/src/trusted/service_runtime/win/sel_segments.c b/src/trusted/service_runtime/win/sel_segments.c
index f18785d9a..fd5dd4fdd 100644
--- a/src/trusted/service_runtime/win/sel_segments.c
+++ b/src/trusted/service_runtime/win/sel_segments.c
@@ -16,7 +16,11 @@
uint16_t NaClGetCs(void) {
uint16_t seg1;
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %%cs, %0" : "=r"(seg1));
+#else
__asm mov seg1, cs;
+#endif
return seg1;
}
@@ -25,59 +29,95 @@ uint16_t NaClGetCs(void) {
uint16_t NaClGetDs(void) {
uint16_t seg1;
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %%ds, %0" : "=r"(seg1));
+#else
__asm mov seg1, ds;
+#endif
return seg1;
}
void NaClSetDs(uint16_t seg1) {
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %0, %%ds" : : "r"(seg1));
+#else
__asm mov ds, seg1;
+#endif
}
uint16_t NaClGetEs(void) {
uint16_t seg1;
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %%es, %0" : "=r"(seg1));
+#else
__asm mov seg1, es;
+#endif
return seg1;
}
void NaClSetEs(uint16_t seg1) {
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %0, %%es" : : "r"(seg1));
+#else
__asm mov es, seg1;
+#endif
}
uint16_t NaClGetFs(void) {
uint16_t seg1;
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %%fs, %0" : "=r"(seg1));
+#else
__asm mov seg1, fs;
+#endif
return seg1;
}
void NaClSetFs(uint16_t seg1) {
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %0, %%fs" : : "r"(seg1));
+#else
__asm mov fs, seg1;
+#endif
}
uint16_t NaClGetGs(void) {
uint16_t seg1;
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %%gs, %0" : "=r"(seg1));
+#else
__asm mov seg1, gs;
+#endif
return seg1;
}
void NaClSetGs(uint16_t seg1) {
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %0, %%gs" : : "r"(seg1));
+#else
__asm mov gs, seg1;
+#endif
}
uint16_t NaClGetSs(void) {
uint16_t seg1;
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %%ss, %0" : "=r"(seg1));
+#else
__asm mov seg1, ss;
+#endif
return seg1;
}
@@ -85,7 +125,11 @@ uint16_t NaClGetSs(void) {
uint32_t NaClGetStackPtr(void) {
uint32_t stack_ptr;
+#if defined(__GNUC__)
+ __asm__ volatile ("mov %%esp, %0" : "=r"(stack_ptr));
+#else
_asm mov stack_ptr, esp;
+#endif
return stack_ptr;
}
#endif
diff --git a/tests/trusted_crash/crash_in_syscall/test_host.c b/tests/trusted_crash/crash_in_syscall/test_host.c
index 1e8f0919c..4cf25deff 100644
--- a/tests/trusted_crash/crash_in_syscall/test_host.c
+++ b/tests/trusted_crash/crash_in_syscall/test_host.c
@@ -127,7 +127,7 @@ static void Backtrace(CONTEXT *initial_context) {
}
fprintf(stderr, "#%i: ip=%p stack=%llx frame=%llx ",
frame_number,
- (void *) frame.AddrPC.Offset,
+ (void *) (uintptr_t) frame.AddrPC.Offset,
frame.AddrStack.Offset,
frame.AddrFrame.Offset);
PrintSymbolForAddress(frame.AddrPC.Offset);