summaryrefslogtreecommitdiffstats
path: root/mozglue/build
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /mozglue/build
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'mozglue/build')
-rw-r--r--mozglue/build/AsanOptions.cpp35
-rw-r--r--mozglue/build/BionicGlue.cpp157
-rw-r--r--mozglue/build/Makefile.in23
-rw-r--r--mozglue/build/SSE.cpp206
-rw-r--r--mozglue/build/SSE.h332
-rw-r--r--mozglue/build/WindowsDllBlocklist.cpp831
-rw-r--r--mozglue/build/WindowsDllBlocklist.h39
-rw-r--r--mozglue/build/arm-eabi-filter4
-rw-r--r--mozglue/build/arm.cpp147
-rw-r--r--mozglue/build/arm.h146
-rw-r--r--mozglue/build/cpuacct.c61
-rw-r--r--mozglue/build/cpuacct.h41
-rw-r--r--mozglue/build/dummy.cpp6
-rw-r--r--mozglue/build/mips.cpp47
-rw-r--r--mozglue/build/mips.h29
-rw-r--r--mozglue/build/moz.build108
-rw-r--r--mozglue/build/mozglue.def.in39
-rw-r--r--mozglue/build/replace_malloc.mk32
18 files changed, 2283 insertions, 0 deletions
diff --git a/mozglue/build/AsanOptions.cpp b/mozglue/build/AsanOptions.cpp
new file mode 100644
index 000000000..729c61ef3
--- /dev/null
+++ b/mozglue/build/AsanOptions.cpp
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/Attributes.h"
+
+#ifndef _MSC_VER // Not supported by clang-cl yet
+
+// When running with AddressSanitizer, we need to explicitly set some
+// options specific to our codebase to prevent errors during runtime.
+// To override these, set the ASAN_OPTIONS environment variable.
+//
+// Currently, these are:
+//
+// allow_user_segv_handler=1 - Tell ASan to allow our code to use its
+// own SIGSEGV handlers. This is required by ASM.js internally.
+//
+// alloc_dealloc_mismatch=0 - Disable alloc-dealloc mismatch checking
+// in ASan. This is required because we define our own new/delete
+// operators that are backed by malloc/free. If one of them gets inlined
+// while the other doesn't, ASan will report false positives.
+//
+// detect_leaks=0 - Disable LeakSanitizer. This is required because
+// otherwise leak checking will be enabled for various building and
+// testing executables where we don't care much about leaks. Enabling
+// this will also likely require setting LSAN_OPTIONS with a suppression
+// file, as in build/sanitizers/lsan_suppressions.txt.
+//
+extern "C" MOZ_ASAN_BLACKLIST
+const char* __asan_default_options() {
+ return "allow_user_segv_handler=1:alloc_dealloc_mismatch=0:detect_leaks=0";
+}
+
+#endif
diff --git a/mozglue/build/BionicGlue.cpp b/mozglue/build/BionicGlue.cpp
new file mode 100644
index 000000000..208fcce68
--- /dev/null
+++ b/mozglue/build/BionicGlue.cpp
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <pthread.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <android/log.h>
+#include <sys/syscall.h>
+
+#include "mozilla/Alignment.h"
+
+#include <vector>
+
+#define NS_EXPORT __attribute__ ((visibility("default")))
+
+#if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID)
+/* Android doesn't have pthread_atfork(), so we need to use our own. */
+struct AtForkFuncs {
+ void (*prepare)(void);
+ void (*parent)(void);
+ void (*child)(void);
+};
+
+/* jemalloc's initialization calls pthread_atfork. When pthread_atfork (see
+ * further below) stores the corresponding data, it's going to allocate memory,
+ * which will loop back to jemalloc's initialization, leading to a dead-lock.
+ * So, for that specific vector, we use a special allocator that returns a
+ * static buffer for small sizes, and force the initial vector capacity to
+ * a size enough to store one atfork function table. */
+template <typename T>
+struct SpecialAllocator: public std::allocator<T>
+{
+ SpecialAllocator(): bufUsed(false) {}
+
+ inline typename std::allocator<T>::pointer allocate(typename std::allocator<T>::size_type n, const void * = 0) {
+ if (!bufUsed && n == 1) {
+ bufUsed = true;
+ return buf.addr();
+ }
+ return reinterpret_cast<T *>(::operator new(sizeof(T) * n));
+ }
+
+ inline void deallocate(typename std::allocator<T>::pointer p, typename std::allocator<T>::size_type n) {
+ if (p == buf.addr())
+ bufUsed = false;
+ else
+ ::operator delete(p);
+ }
+
+ template<typename U>
+ struct rebind {
+ typedef SpecialAllocator<U> other;
+ };
+
+private:
+ mozilla::AlignedStorage2<T> buf;
+ bool bufUsed;
+};
+
+static std::vector<AtForkFuncs, SpecialAllocator<AtForkFuncs> > atfork;
+#endif
+
+#ifdef MOZ_WIDGET_GONK
+#include "cpuacct.h"
+
+#if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID)
+extern "C" NS_EXPORT int
+timer_create(clockid_t, struct sigevent*, timer_t*)
+{
+ __android_log_print(ANDROID_LOG_ERROR, "BionicGlue", "timer_create not supported!");
+ abort();
+ return -1;
+}
+#endif
+
+#else
+#define cpuacct_add(x)
+#endif
+
+#if ANDROID_VERSION < 17 || defined(MOZ_WIDGET_ANDROID)
+extern "C" NS_EXPORT int
+pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
+{
+ AtForkFuncs funcs;
+ funcs.prepare = prepare;
+ funcs.parent = parent;
+ funcs.child = child;
+ if (!atfork.capacity())
+ atfork.reserve(1);
+ atfork.push_back(funcs);
+ return 0;
+}
+
+extern "C" NS_EXPORT pid_t __fork(void);
+
+extern "C" NS_EXPORT pid_t
+fork(void)
+{
+ pid_t pid;
+ for (auto it = atfork.rbegin();
+ it < atfork.rend(); ++it)
+ if (it->prepare)
+ it->prepare();
+
+ switch ((pid = syscall(__NR_clone, SIGCHLD, NULL, NULL, NULL, NULL))) {
+ case 0:
+ cpuacct_add(getuid());
+ for (auto it = atfork.begin();
+ it < atfork.end(); ++it)
+ if (it->child)
+ it->child();
+ break;
+ default:
+ for (auto it = atfork.begin();
+ it < atfork.end(); ++it)
+ if (it->parent)
+ it->parent();
+ }
+ return pid;
+}
+#endif
+
+extern "C" NS_EXPORT int
+raise(int sig)
+{
+ // Bug 741272: Bionic incorrectly uses kill(), which signals the
+ // process, and thus could signal another thread (and let this one
+ // return "successfully" from raising a fatal signal).
+ //
+ // Bug 943170: POSIX specifies pthread_kill(pthread_self(), sig) as
+ // equivalent to raise(sig), but Bionic also has a bug with these
+ // functions, where a forked child will kill its parent instead.
+
+ extern pid_t gettid(void);
+ return syscall(__NR_tgkill, getpid(), gettid(), sig);
+}
+
+/* Flash plugin uses symbols that are not present in Android >= 4.4 */
+#ifndef MOZ_WIDGET_GONK
+namespace android {
+ namespace VectorImpl {
+ NS_EXPORT void reservedVectorImpl1(void) { }
+ NS_EXPORT void reservedVectorImpl2(void) { }
+ NS_EXPORT void reservedVectorImpl3(void) { }
+ NS_EXPORT void reservedVectorImpl4(void) { }
+ NS_EXPORT void reservedVectorImpl5(void) { }
+ NS_EXPORT void reservedVectorImpl6(void) { }
+ NS_EXPORT void reservedVectorImpl7(void) { }
+ NS_EXPORT void reservedVectorImpl8(void) { }
+ }
+}
+#endif
+
diff --git a/mozglue/build/Makefile.in b/mozglue/build/Makefile.in
new file mode 100644
index 000000000..1cfa41ea0
--- /dev/null
+++ b/mozglue/build/Makefile.in
@@ -0,0 +1,23 @@
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# For FORCE_SHARED_LIB
+include $(topsrcdir)/config/config.mk
+
+ifeq (WINNT,$(OS_TARGET))
+mozglue.def: mozglue.def.in $(GLOBAL_DEPS)
+ $(call py_action,preprocessor,$(if $(MOZ_REPLACE_MALLOC),-DMOZ_REPLACE_MALLOC) $(ACDEFINES) $< -o $@)
+
+GARBAGE += mozglue.def
+endif
+
+include $(topsrcdir)/mozglue/build/replace_malloc.mk
+
+ifdef MOZ_LINKER
+ifeq (arm, $(TARGET_CPU))
+OS_LDFLAGS += -Wl,-version-script,$(srcdir)/arm-eabi-filter
+endif
+
+endif
diff --git a/mozglue/build/SSE.cpp b/mozglue/build/SSE.cpp
new file mode 100644
index 000000000..8ad228684
--- /dev/null
+++ b/mozglue/build/SSE.cpp
@@ -0,0 +1,206 @@
+/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* compile-time and runtime tests for whether to use SSE instructions */
+
+#include "SSE.h"
+
+#ifdef HAVE_CPUID_H
+// cpuid.h is available on gcc 4.3 and higher on i386 and x86_64
+#include <cpuid.h>
+#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))
+// MSVC 2005 or newer on x86-32 or x86-64
+#include <intrin.h>
+#endif
+
+namespace {
+
+// SSE.h has parallel #ifs which declare MOZILLA_SSE_HAVE_CPUID_DETECTION.
+// We can't declare these functions in the header file, however, because
+// <intrin.h> conflicts with <windows.h> on MSVC 2005, and some files want to
+// include both SSE.h and <windows.h>.
+
+#ifdef HAVE_CPUID_H
+
+enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 };
+
+static bool
+has_cpuid_bits(unsigned int level, CPUIDRegister reg, unsigned int bits)
+{
+ unsigned int regs[4];
+ unsigned int eax, ebx, ecx, edx;
+ unsigned max = __get_cpuid_max(0, NULL);
+ if (level > max)
+ return false;
+ __cpuid_count(level, 0, eax, ebx, ecx, edx);
+ regs[0] = eax;
+ regs[1] = ebx;
+ regs[2] = ecx;
+ regs[3] = edx;
+ return (regs[reg] & bits) == bits;
+}
+
+#if !defined(MOZILLA_PRESUME_AVX)
+static uint64_t xgetbv(uint32_t xcr) {
+ uint32_t eax, edx;
+ __asm__ ( ".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(xcr));
+ return (uint64_t)(edx) << 32 | eax;
+}
+#endif
+
+#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))
+
+enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 };
+
+static bool
+has_cpuid_bits(unsigned int level, CPUIDRegister reg, unsigned int bits)
+{
+ // Check that the level in question is supported.
+ int regs[4];
+ __cpuid(regs, level & 0x80000000u);
+ if (unsigned(regs[0]) < level)
+ return false;
+
+ // "The __cpuid intrinsic clears the ECX register before calling the cpuid instruction."
+ __cpuid(regs, level);
+ return (unsigned(regs[reg]) & bits) == bits;
+}
+
+#if !defined(MOZILLA_PRESUME_AVX)
+static uint64_t xgetbv(uint32_t xcr) { return _xgetbv(xcr); }
+#endif
+
+#elif (defined(__GNUC__) || defined(__SUNPRO_CC)) && (defined(__i386) || defined(__x86_64__))
+
+enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 };
+
+#ifdef __i386
+static void
+moz_cpuid(int CPUInfo[4], int InfoType)
+{
+ asm (
+ "xchg %esi, %ebx\n"
+ "xor %ecx, %ecx\n" // ecx is the sub-leaf (we only ever need 0)
+ "cpuid\n"
+ "movl %eax, (%edi)\n"
+ "movl %ebx, 4(%edi)\n"
+ "movl %ecx, 8(%edi)\n"
+ "movl %edx, 12(%edi)\n"
+ "xchg %esi, %ebx\n"
+ :
+ : "a"(InfoType), // %eax
+ "D"(CPUInfo) // %edi
+ : "%ecx", "%edx", "%esi"
+ );
+}
+#else
+static void
+moz_cpuid(int CPUInfo[4], int InfoType)
+{
+ asm (
+ "xchg %rsi, %rbx\n"
+ "xor %ecx, %ecx\n" // ecx is the sub-leaf (we only ever need 0)
+ "cpuid\n"
+ "movl %eax, (%rdi)\n"
+ "movl %ebx, 4(%rdi)\n"
+ "movl %ecx, 8(%rdi)\n"
+ "movl %edx, 12(%rdi)\n"
+ "xchg %rsi, %rbx\n"
+ :
+ : "a"(InfoType), // %eax
+ "D"(CPUInfo) // %rdi
+ : "%ecx", "%edx", "%rsi"
+ );
+}
+#endif
+
+static bool
+has_cpuid_bits(unsigned int level, CPUIDRegister reg, unsigned int bits)
+{
+ // Check that the level in question is supported.
+ volatile int regs[4];
+ moz_cpuid((int *)regs, level & 0x80000000u);
+ if (unsigned(regs[0]) < level)
+ return false;
+
+ moz_cpuid((int *)regs, level);
+ return (unsigned(regs[reg]) & bits) == bits;
+}
+
+#endif // end CPUID declarations
+
+} // namespace
+
+namespace mozilla {
+
+namespace sse_private {
+
+#if defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+
+#if !defined(MOZILLA_PRESUME_MMX)
+ bool mmx_enabled = has_cpuid_bits(1u, edx, (1u<<23));
+#endif
+
+#if !defined(MOZILLA_PRESUME_SSE)
+ bool sse_enabled = has_cpuid_bits(1u, edx, (1u<<25));
+#endif
+
+#if !defined(MOZILLA_PRESUME_SSE2)
+ bool sse2_enabled = has_cpuid_bits(1u, edx, (1u<<26));
+#endif
+
+#if !defined(MOZILLA_PRESUME_SSE3)
+ bool sse3_enabled = has_cpuid_bits(1u, ecx, (1u<<0));
+#endif
+
+#if !defined(MOZILLA_PRESUME_SSSE3)
+ bool ssse3_enabled = has_cpuid_bits(1u, ecx, (1u<<9));
+#endif
+
+#if !defined(MOZILLA_PRESUME_SSE4A)
+ bool sse4a_enabled = has_cpuid_bits(0x80000001u, ecx, (1u<<6));
+#endif
+
+#if !defined(MOZILLA_PRESUME_SSE4_1)
+ bool sse4_1_enabled = has_cpuid_bits(1u, ecx, (1u<<19));
+#endif
+
+#if !defined(MOZILLA_PRESUME_SSE4_2)
+ bool sse4_2_enabled = has_cpuid_bits(1u, ecx, (1u<<20));
+#endif
+
+#if !defined(MOZILLA_PRESUME_AVX) || !defined(MOZILLA_PRESUME_AVX2)
+ static bool has_avx()
+ {
+#if defined(MOZILLA_PRESUME_AVX)
+ return true;
+#else
+ const unsigned AVX = 1u << 28;
+ const unsigned OSXSAVE = 1u << 27;
+ const unsigned XSAVE = 1u << 26;
+
+ const unsigned XMM_STATE = 1u << 1;
+ const unsigned YMM_STATE = 1u << 2;
+ const unsigned AVX_STATE = XMM_STATE | YMM_STATE;
+
+ return has_cpuid_bits(1u, ecx, AVX | OSXSAVE | XSAVE) &&
+ // ensure the OS supports XSAVE of YMM registers
+ (xgetbv(0) & AVX_STATE) == AVX_STATE;
+#endif // MOZILLA_PRESUME_AVX
+ }
+#endif // !MOZILLA_PRESUME_AVX || !MOZILLA_PRESUME_AVX2
+
+#if !defined(MOZILLA_PRESUME_AVX)
+ bool avx_enabled = has_avx();
+#endif
+
+#if !defined(MOZILLA_PRESUME_AVX2)
+ bool avx2_enabled = has_avx() && has_cpuid_bits(7u, ebx, (1u<<5));
+#endif
+
+#endif
+
+} // namespace sse_private
+} // namespace mozilla
diff --git a/mozglue/build/SSE.h b/mozglue/build/SSE.h
new file mode 100644
index 000000000..fe7788640
--- /dev/null
+++ b/mozglue/build/SSE.h
@@ -0,0 +1,332 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* compile-time and runtime tests for whether to use SSE instructions */
+
+#ifndef mozilla_SSE_h_
+#define mozilla_SSE_h_
+
+// for definition of MFBT_DATA
+#include "mozilla/Types.h"
+
+/**
+ * The public interface of this header consists of a set of macros and
+ * functions for Intel CPU features.
+ *
+ * DETECTING ISA EXTENSIONS
+ * ========================
+ *
+ * This header provides the following functions for determining whether the
+ * current CPU supports a particular instruction set extension:
+ *
+ * mozilla::supports_mmx
+ * mozilla::supports_sse
+ * mozilla::supports_sse2
+ * mozilla::supports_sse3
+ * mozilla::supports_ssse3
+ * mozilla::supports_sse4a
+ * mozilla::supports_sse4_1
+ * mozilla::supports_sse4_2
+ * mozilla::supports_avx
+ * mozilla::supports_avx2
+ *
+ * If you're writing code using inline assembly, you should guard it with a
+ * call to one of these functions. For instance:
+ *
+ * if (mozilla::supports_sse2()) {
+ * asm(" ... ");
+ * }
+ * else {
+ * ...
+ * }
+ *
+ * Note that these functions depend on cpuid intrinsics only available in gcc
+ * 4.3 or later and MSVC 8.0 (Visual C++ 2005) or later, so they return false
+ * in older compilers. (This could be fixed by replacing the code with inline
+ * assembly.)
+ *
+ *
+ * USING INTRINSICS
+ * ================
+ *
+ * This header also provides support for coding using CPU intrinsics.
+ *
+ * For each mozilla::supports_abc function, we define a MOZILLA_MAY_SUPPORT_ABC
+ * macro which indicates that the target/compiler combination we're using is
+ * compatible with the ABC extension. For instance, x86_64 with MSVC 2003 is
+ * compatible with SSE2 but not SSE3, since although there exist x86_64 CPUs
+ * with SSE3 support, MSVC 2003 only supports through SSE2.
+ *
+ * Until gcc fixes #pragma target [1] [2] or our x86 builds require SSE2,
+ * you'll need to separate code using intrinsics into a file separate from your
+ * regular code. Here's the recommended pattern:
+ *
+ * #ifdef MOZILLA_MAY_SUPPORT_ABC
+ * namespace mozilla {
+ * namespace ABC {
+ * void foo();
+ * }
+ * }
+ * #endif
+ *
+ * void foo() {
+ * #ifdef MOZILLA_MAY_SUPPORT_ABC
+ * if (mozilla::supports_abc()) {
+ * mozilla::ABC::foo(); // in a separate file
+ * return;
+ * }
+ * #endif
+ *
+ * foo_unvectorized();
+ * }
+ *
+ * You'll need to define mozilla::ABC::foo() in a separate file and add the
+ * -mabc flag when using gcc.
+ *
+ * [1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39787 and
+ * [2] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41201 being fixed.
+ *
+ */
+
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
+#ifdef __MMX__
+ // It's ok to use MMX instructions based on the -march option (or
+ // the default for x86_64 or for Intel Mac).
+ #define MOZILLA_PRESUME_MMX 1
+#endif
+#ifdef __SSE__
+ // It's ok to use SSE instructions based on the -march option (or
+ // the default for x86_64 or for Intel Mac).
+ #define MOZILLA_PRESUME_SSE 1
+#endif
+#ifdef __SSE2__
+ // It's ok to use SSE2 instructions based on the -march option (or
+ // the default for x86_64 or for Intel Mac).
+ #define MOZILLA_PRESUME_SSE2 1
+#endif
+#ifdef __SSE3__
+ // It's ok to use SSE3 instructions based on the -march option (or the
+ // default for Intel Mac).
+ #define MOZILLA_PRESUME_SSE3 1
+#endif
+#ifdef __SSSE3__
+ // It's ok to use SSSE3 instructions based on the -march option.
+ #define MOZILLA_PRESUME_SSSE3 1
+#endif
+#ifdef __SSE4A__
+ // It's ok to use SSE4A instructions based on the -march option.
+ #define MOZILLA_PRESUME_SSE4A 1
+#endif
+#ifdef __SSE4_1__
+ // It's ok to use SSE4.1 instructions based on the -march option.
+ #define MOZILLA_PRESUME_SSE4_1 1
+#endif
+#ifdef __SSE4_2__
+ // It's ok to use SSE4.2 instructions based on the -march option.
+ #define MOZILLA_PRESUME_SSE4_2 1
+#endif
+#ifdef __AVX__
+ // It's ok to use AVX instructions based on the -march option.
+ #define MOZILLA_PRESUME_AVX 1
+#endif
+#ifdef __AVX2__
+ // It's ok to use AVX instructions based on the -march option.
+ #define MOZILLA_PRESUME_AVX2 1
+#endif
+
+
+
+#ifdef HAVE_CPUID_H
+ #define MOZILLA_SSE_HAVE_CPUID_DETECTION
+#endif
+
+#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64))
+
+#define MOZILLA_SSE_HAVE_CPUID_DETECTION
+
+#if defined(_M_IX86_FP)
+
+#if _M_IX86_FP >= 1
+ // It's ok to use SSE instructions based on the /arch option
+ #define MOZILLA_PRESUME_SSE
+#endif
+#if _M_IX86_FP >= 2
+ // It's ok to use SSE2 instructions based on the /arch option
+ #define MOZILLA_PRESUME_SSE2
+#endif
+
+#elif defined(_M_AMD64)
+ // MSVC for AMD64 doesn't support MMX, so don't presume it here.
+
+ // SSE is always available on AMD64.
+ #define MOZILLA_PRESUME_SSE
+ // SSE2 is always available on AMD64.
+ #define MOZILLA_PRESUME_SSE2
+#endif
+
+#elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__))
+// Sun Studio on x86 or amd64
+
+#define MOZILLA_SSE_HAVE_CPUID_DETECTION
+
+#if defined(__x86_64__)
+ // MMX is always available on AMD64.
+ #define MOZILLA_PRESUME_MMX
+ // SSE is always available on AMD64.
+ #define MOZILLA_PRESUME_SSE
+ // SSE2 is always available on AMD64.
+ #define MOZILLA_PRESUME_SSE2
+#endif
+
+#endif
+
+namespace mozilla {
+
+ namespace sse_private {
+#if defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#if !defined(MOZILLA_PRESUME_MMX)
+ extern bool MFBT_DATA mmx_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_SSE)
+ extern bool MFBT_DATA sse_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_SSE2)
+ extern bool MFBT_DATA sse2_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_SSE3)
+ extern bool MFBT_DATA sse3_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_SSSE3)
+ extern bool MFBT_DATA ssse3_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_SSE4A)
+ extern bool MFBT_DATA sse4a_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_SSE4_1)
+ extern bool MFBT_DATA sse4_1_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_SSE4_2)
+ extern bool MFBT_DATA sse4_2_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_AVX)
+ extern bool MFBT_DATA avx_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_AVX2)
+ extern bool MFBT_DATA avx2_enabled;
+#endif
+
+
+#endif
+ } // namespace sse_private
+
+#if defined(MOZILLA_PRESUME_MMX)
+#define MOZILLA_MAY_SUPPORT_MMX 1
+ inline bool supports_mmx() { return true; }
+#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#if !(defined(_MSC_VER) && defined(_M_AMD64))
+ // Define MOZILLA_MAY_SUPPORT_MMX only if we're not on MSVC for
+ // AMD64, since that compiler doesn't support MMX.
+#define MOZILLA_MAY_SUPPORT_MMX 1
+#endif
+ inline bool supports_mmx() { return sse_private::mmx_enabled; }
+#else
+ inline bool supports_mmx() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_SSE)
+#define MOZILLA_MAY_SUPPORT_SSE 1
+ inline bool supports_sse() { return true; }
+#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#define MOZILLA_MAY_SUPPORT_SSE 1
+ inline bool supports_sse() { return sse_private::sse_enabled; }
+#else
+ inline bool supports_sse() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_SSE2)
+#define MOZILLA_MAY_SUPPORT_SSE2 1
+ inline bool supports_sse2() { return true; }
+#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#define MOZILLA_MAY_SUPPORT_SSE2 1
+ inline bool supports_sse2() { return sse_private::sse2_enabled; }
+#else
+ inline bool supports_sse2() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_SSE3)
+#define MOZILLA_MAY_SUPPORT_SSE3 1
+ inline bool supports_sse3() { return true; }
+#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#define MOZILLA_MAY_SUPPORT_SSE3 1
+ inline bool supports_sse3() { return sse_private::sse3_enabled; }
+#else
+ inline bool supports_sse3() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_SSSE3)
+#define MOZILLA_MAY_SUPPORT_SSSE3 1
+ inline bool supports_ssse3() { return true; }
+#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#define MOZILLA_MAY_SUPPORT_SSSE3 1
+ inline bool supports_ssse3() { return sse_private::ssse3_enabled; }
+#else
+ inline bool supports_ssse3() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_SSE4A)
+#define MOZILLA_MAY_SUPPORT_SSE4A 1
+ inline bool supports_sse4a() { return true; }
+#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#define MOZILLA_MAY_SUPPORT_SSE4A 1
+ inline bool supports_sse4a() { return sse_private::sse4a_enabled; }
+#else
+ inline bool supports_sse4a() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_SSE4_1)
+#define MOZILLA_MAY_SUPPORT_SSE4_1 1
+ inline bool supports_sse4_1() { return true; }
+#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#define MOZILLA_MAY_SUPPORT_SSE4_1 1
+ inline bool supports_sse4_1() { return sse_private::sse4_1_enabled; }
+#else
+ inline bool supports_sse4_1() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_SSE4_2)
+#define MOZILLA_MAY_SUPPORT_SSE4_2 1
+ inline bool supports_sse4_2() { return true; }
+#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#define MOZILLA_MAY_SUPPORT_SSE4_2 1
+ inline bool supports_sse4_2() { return sse_private::sse4_2_enabled; }
+#else
+ inline bool supports_sse4_2() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_AVX)
+#define MOZILLA_MAY_SUPPORT_AVX 1
+ inline bool supports_avx() { return true; }
+#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#define MOZILLA_MAY_SUPPORT_AVX 1
+ inline bool supports_avx() { return sse_private::avx_enabled; }
+#else
+ inline bool supports_avx() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_AVX2)
+#define MOZILLA_MAY_SUPPORT_AVX2 1
+ inline bool supports_avx2() { return true; }
+#elif defined(MOZILLA_SSE_HAVE_CPUID_DETECTION)
+#define MOZILLA_MAY_SUPPORT_AVX2 1
+ inline bool supports_avx2() { return sse_private::avx2_enabled; }
+#else
+ inline bool supports_avx2() { return false; }
+#endif
+
+
+} // namespace mozilla
+
+#endif /* !defined(mozilla_SSE_h_) */
diff --git a/mozglue/build/WindowsDllBlocklist.cpp b/mozglue/build/WindowsDllBlocklist.cpp
new file mode 100644
index 000000000..a3c662723
--- /dev/null
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -0,0 +1,831 @@
+/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifdef MOZ_MEMORY
+#define MOZ_MEMORY_IMPL
+#include "mozmemory_wrap.h"
+#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
+// See mozmemory_wrap.h for more details. This file is part of libmozglue, so
+// it needs to use _impl suffixes.
+#define MALLOC_DECL(name, return_type, ...) \
+ extern "C" MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
+#include "malloc_decls.h"
+#endif
+
+#include <windows.h>
+#include <winternl.h>
+#include <io.h>
+
+#pragma warning( push )
+#pragma warning( disable : 4275 4530 ) // See msvc-stl-wrapper.template.h
+#include <map>
+#pragma warning( pop )
+
+#include "nsAutoPtr.h"
+
+#include "nsWindowsDllInterceptor.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/WindowsVersion.h"
+#include "nsWindowsHelpers.h"
+#include "WindowsDllBlocklist.h"
+
+using namespace mozilla;
+
+#define ALL_VERSIONS ((unsigned long long)-1LL)
+
+// DLLs sometimes ship without a version number, particularly early
+// releases. Blocking "version <= 0" has the effect of blocking unversioned
+// DLLs (since the call to get version info fails), but not blocking
+// any versioned instance.
+#define UNVERSIONED ((unsigned long long)0LL)
+
+// Convert the 4 (decimal) components of a DLL version number into a
+// single unsigned long long, as needed by the blocklist
+#define MAKE_VERSION(a,b,c,d)\
+ ((a##ULL << 48) + (b##ULL << 32) + (c##ULL << 16) + d##ULL)
+
+struct DllBlockInfo {
+ // The name of the DLL -- in LOWERCASE! It will be compared to
+ // a lowercase version of the DLL name only.
+ const char *name;
+
+ // If maxVersion is ALL_VERSIONS, we'll block all versions of this
+ // dll. Otherwise, we'll block all versions less than or equal to
+ // the given version, as queried by GetFileVersionInfo and
+ // VS_FIXEDFILEINFO's dwFileVersionMS and dwFileVersionLS fields.
+ //
+ // Note that the version is usually 4 components, which is A.B.C.D
+ // encoded as 0x AAAA BBBB CCCC DDDD ULL (spaces added for clarity),
+ // but it's not required to be of that format.
+ //
+ // If the USE_TIMESTAMP flag is set, then we use the timestamp from
+ // the IMAGE_FILE_HEADER in lieu of a version number.
+ unsigned long long maxVersion;
+
+ enum {
+ FLAGS_DEFAULT = 0,
+ BLOCK_WIN8PLUS_ONLY = 1,
+ BLOCK_XP_ONLY = 2,
+ USE_TIMESTAMP = 4,
+ } flags;
+};
+
+static DllBlockInfo sWindowsDllBlocklist[] = {
+ // EXAMPLE:
+ // { "uxtheme.dll", ALL_VERSIONS },
+ // { "uxtheme.dll", 0x0000123400000000ULL },
+ // The DLL name must be in lowercase!
+ // The version field is a maximum, that is, we block anything that is
+ // less-than or equal to that version.
+
+ // NPFFAddon - Known malware
+ { "npffaddon.dll", ALL_VERSIONS},
+
+ // AVG 8 - Antivirus vendor AVG, old version, plugin already blocklisted
+ {"avgrsstx.dll", MAKE_VERSION(8,5,0,401)},
+
+ // calc.dll - Suspected malware
+ {"calc.dll", MAKE_VERSION(1,0,0,1)},
+
+ // hook.dll - Suspected malware
+ {"hook.dll", ALL_VERSIONS},
+
+ // GoogleDesktopNetwork3.dll - Extremely old, unversioned instances
+ // of this DLL cause crashes
+ {"googledesktopnetwork3.dll", UNVERSIONED},
+
+ // rdolib.dll - Suspected malware
+ {"rdolib.dll", MAKE_VERSION(6,0,88,4)},
+
+ // fgjk4wvb.dll - Suspected malware
+ {"fgjk4wvb.dll", MAKE_VERSION(8,8,8,8)},
+
+ // radhslib.dll - Naomi internet filter - unmaintained since 2006
+ {"radhslib.dll", UNVERSIONED},
+
+ // Music download filter for vkontakte.ru - old instances
+ // of this DLL cause crashes
+ {"vksaver.dll", MAKE_VERSION(2,2,2,0)},
+
+ // Topcrash in Firefox 4.0b1
+ {"rlxf.dll", MAKE_VERSION(1,2,323,1)},
+
+ // psicon.dll - Topcrashes in Thunderbird, and some crashes in Firefox
+ // Adobe photoshop library, now redundant in later installations
+ {"psicon.dll", ALL_VERSIONS},
+
+ // Topcrash in Firefox 4 betas (bug 618899)
+ {"accelerator.dll", MAKE_VERSION(3,2,1,6)},
+
+ // Topcrash with Roboform in Firefox 8 (bug 699134)
+ {"rf-firefox.dll", MAKE_VERSION(7,6,1,0)},
+ {"roboform.dll", MAKE_VERSION(7,6,1,0)},
+
+ // Topcrash with Babylon Toolbar on FF16+ (bug 721264)
+ {"babyfox.dll", ALL_VERSIONS},
+
+ // sprotector.dll crashes, bug 957258
+ {"sprotector.dll", ALL_VERSIONS},
+
+ // leave these two in always for tests
+ { "mozdllblockingtest.dll", ALL_VERSIONS },
+ { "mozdllblockingtest_versioned.dll", 0x0000000400000000ULL },
+
+ // Windows Media Foundation FLAC decoder and type sniffer (bug 839031).
+ { "mfflac.dll", ALL_VERSIONS },
+
+ // Older Relevant Knowledge DLLs cause us to crash (bug 904001).
+ { "rlnx.dll", MAKE_VERSION(1, 3, 334, 9) },
+ { "pmnx.dll", MAKE_VERSION(1, 3, 334, 9) },
+ { "opnx.dll", MAKE_VERSION(1, 3, 334, 9) },
+ { "prnx.dll", MAKE_VERSION(1, 3, 334, 9) },
+
+ // Older belgian ID card software causes Firefox to crash or hang on
+ // shutdown, bug 831285 and 918399.
+ { "beid35cardlayer.dll", MAKE_VERSION(3, 5, 6, 6968) },
+
+ // bug 925459, bitguard crashes
+ { "bitguard.dll", ALL_VERSIONS },
+
+ // bug 812683 - crashes in Windows library when Asus Gamer OSD is installed
+ // Software is discontinued/unsupported
+ { "atkdx11disp.dll", ALL_VERSIONS },
+
+ // Topcrash with Conduit SearchProtect, bug 944542
+ { "spvc32.dll", ALL_VERSIONS },
+
+ // XP topcrash with F-Secure, bug 970362
+ { "fs_ccf_ni_umh32.dll", MAKE_VERSION(1, 42, 101, 0), DllBlockInfo::BLOCK_XP_ONLY },
+
+ // Topcrash with V-bates, bug 1002748 and bug 1023239
+ { "libinject.dll", UNVERSIONED },
+ { "libinject2.dll", 0x537DDC93, DllBlockInfo::USE_TIMESTAMP },
+ { "libredir2.dll", 0x5385B7ED, DllBlockInfo::USE_TIMESTAMP },
+
+ // Crashes with RoboForm2Go written against old SDK, bug 988311/1196859
+ { "rf-firefox-22.dll", ALL_VERSIONS },
+ { "rf-firefox-40.dll", ALL_VERSIONS },
+
+ // Crashes with DesktopTemperature, bug 1046382
+ { "dtwxsvc.dll", 0x53153234, DllBlockInfo::USE_TIMESTAMP },
+
+ // Startup crashes with Lenovo Onekey Theater, bug 1123778
+ { "activedetect32.dll", UNVERSIONED },
+ { "activedetect64.dll", UNVERSIONED },
+ { "windowsapihookdll32.dll", UNVERSIONED },
+ { "windowsapihookdll64.dll", UNVERSIONED },
+
+ // Flash crashes with RealNetworks RealDownloader, bug 1132663
+ { "rndlnpshimswf.dll", ALL_VERSIONS },
+ { "rndlmainbrowserrecordplugin.dll", ALL_VERSIONS },
+
+ // Startup crashes with RealNetworks Browser Record Plugin, bug 1170141
+ { "nprpffbrowserrecordext.dll", ALL_VERSIONS },
+ { "nprndlffbrowserrecordext.dll", ALL_VERSIONS },
+
+ // Crashes with CyberLink YouCam, bug 1136968
+ { "ycwebcamerasource.ax", MAKE_VERSION(2, 0, 0, 1611) },
+
+ // Old version of WebcamMax crashes WebRTC, bug 1130061
+ { "vwcsource.ax", MAKE_VERSION(1, 5, 0, 0) },
+
+ // NetOp School, discontinued product, bug 763395
+ { "nlsp.dll", MAKE_VERSION(6, 23, 2012, 19) },
+
+ // Orbit Downloader, bug 1222819
+ { "grabdll.dll", MAKE_VERSION(2, 6, 1, 0) },
+ { "grabkernel.dll", MAKE_VERSION(1, 0, 0, 1) },
+
+ // ESET, bug 1229252
+ { "eoppmonitor.dll", ALL_VERSIONS },
+
+ // SS2OSD, bug 1262348
+ { "ss2osd.dll", ALL_VERSIONS },
+ { "ss2devprops.dll", ALL_VERSIONS },
+
+ // NHASUSSTRIXOSD.DLL, bug 1269244
+ { "nhasusstrixosd.dll", ALL_VERSIONS },
+ { "nhasusstrixdevprops.dll", ALL_VERSIONS },
+
+ // Crashes with PremierOpinion/RelevantKnowledge, bug 1277846
+ { "opls.dll", ALL_VERSIONS },
+ { "opls64.dll", ALL_VERSIONS },
+ { "pmls.dll", ALL_VERSIONS },
+ { "pmls64.dll", ALL_VERSIONS },
+ { "prls.dll", ALL_VERSIONS },
+ { "prls64.dll", ALL_VERSIONS },
+ { "rlls.dll", ALL_VERSIONS },
+ { "rlls64.dll", ALL_VERSIONS },
+
+ // Vorbis DirectShow filters, bug 1239690.
+ { "vorbis.acm", MAKE_VERSION(0, 0, 3, 6) },
+
+ // AhnLab Internet Security, bug 1311969
+ { "nzbrcom.dll", ALL_VERSIONS },
+
+ // K7TotalSecurity, bug 1339083.
+ { "k7pswsen.dll", MAKE_VERSION(15, 2, 2, 95) },
+
+ { nullptr, 0 }
+};
+
+#ifndef STATUS_DLL_NOT_FOUND
+#define STATUS_DLL_NOT_FOUND ((DWORD)0xC0000135L)
+#endif
+
+// define this for very verbose dll load debug spew
+#undef DEBUG_very_verbose
+
+static const char kBlockedDllsParameter[] = "BlockedDllList=";
+static const int kBlockedDllsParameterLen =
+ sizeof(kBlockedDllsParameter) - 1;
+
+static const char kBlocklistInitFailedParameter[] = "BlocklistInitFailed=1\n";
+static const int kBlocklistInitFailedParameterLen =
+ sizeof(kBlocklistInitFailedParameter) - 1;
+
+static const char kUser32BeforeBlocklistParameter[] = "User32BeforeBlocklist=1\n";
+static const int kUser32BeforeBlocklistParameterLen =
+ sizeof(kUser32BeforeBlocklistParameter) - 1;
+
+static DWORD sThreadLoadingXPCOMModule;
+static bool sBlocklistInitAttempted;
+static bool sBlocklistInitFailed;
+static bool sUser32BeforeBlocklist;
+
+// Duplicated from xpcom glue. Ideally this should be shared.
+void
+printf_stderr(const char *fmt, ...)
+{
+ if (IsDebuggerPresent()) {
+ char buf[2048];
+ va_list args;
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ buf[sizeof(buf) - 1] = '\0';
+ va_end(args);
+ OutputDebugStringA(buf);
+ }
+
+ FILE *fp = _fdopen(_dup(2), "a");
+ if (!fp)
+ return;
+
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(fp, fmt, args);
+ va_end(args);
+
+ fclose(fp);
+}
+
+namespace {
+
+typedef NTSTATUS (NTAPI *LdrLoadDll_func) (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle);
+
+static LdrLoadDll_func stub_LdrLoadDll = 0;
+
+template <class T>
+struct RVAMap {
+ RVAMap(HANDLE map, DWORD offset) {
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+
+ DWORD alignedOffset = (offset / info.dwAllocationGranularity) *
+ info.dwAllocationGranularity;
+
+ MOZ_ASSERT(offset - alignedOffset < info.dwAllocationGranularity, "Wtf");
+
+ mRealView = ::MapViewOfFile(map, FILE_MAP_READ, 0, alignedOffset,
+ sizeof(T) + (offset - alignedOffset));
+
+ mMappedView = mRealView ? reinterpret_cast<T*>((char*)mRealView + (offset - alignedOffset)) :
+ nullptr;
+ }
+ ~RVAMap() {
+ if (mRealView) {
+ ::UnmapViewOfFile(mRealView);
+ }
+ }
+ operator const T*() const { return mMappedView; }
+ const T* operator->() const { return mMappedView; }
+private:
+ const T* mMappedView;
+ void* mRealView;
+};
+
+bool
+CheckASLR(const wchar_t* path)
+{
+ bool retval = false;
+
+ HANDLE file = ::CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ nullptr);
+ if (file != INVALID_HANDLE_VALUE) {
+ HANDLE map = ::CreateFileMappingW(file, nullptr, PAGE_READONLY, 0, 0,
+ nullptr);
+ if (map) {
+ RVAMap<IMAGE_DOS_HEADER> peHeader(map, 0);
+ if (peHeader) {
+ RVAMap<IMAGE_NT_HEADERS> ntHeader(map, peHeader->e_lfanew);
+ if (ntHeader) {
+ // If the DLL has no code, permit it regardless of ASLR status.
+ if (ntHeader->OptionalHeader.SizeOfCode == 0) {
+ retval = true;
+ }
+ // Check to see if the DLL supports ASLR
+ else if ((ntHeader->OptionalHeader.DllCharacteristics &
+ IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) != 0) {
+ retval = true;
+ }
+ }
+ }
+ ::CloseHandle(map);
+ }
+ ::CloseHandle(file);
+ }
+
+ return retval;
+}
+
+DWORD
+GetTimestamp(const wchar_t* path)
+{
+ DWORD timestamp = 0;
+
+ HANDLE file = ::CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ nullptr);
+ if (file != INVALID_HANDLE_VALUE) {
+ HANDLE map = ::CreateFileMappingW(file, nullptr, PAGE_READONLY, 0, 0,
+ nullptr);
+ if (map) {
+ RVAMap<IMAGE_DOS_HEADER> peHeader(map, 0);
+ if (peHeader) {
+ RVAMap<IMAGE_NT_HEADERS> ntHeader(map, peHeader->e_lfanew);
+ if (ntHeader) {
+ timestamp = ntHeader->FileHeader.TimeDateStamp;
+ }
+ }
+ ::CloseHandle(map);
+ }
+ ::CloseHandle(file);
+ }
+
+ return timestamp;
+}
+
+// This lock protects both the reentrancy sentinel and the crash reporter
+// data structures.
+static CRITICAL_SECTION sLock;
+
+/**
+ * Some versions of Windows call LoadLibraryEx to get the version information
+ * for a DLL, which causes our patched LdrLoadDll implementation to re-enter
+ * itself and cause infinite recursion and a stack-exhaustion crash. We protect
+ * against reentrancy by allowing recursive loads of the same DLL.
+ *
+ * Note that we don't use __declspec(thread) because that doesn't work in DLLs
+ * loaded via LoadLibrary and there can be a limited number of TLS slots, so
+ * we roll our own.
+ */
+class ReentrancySentinel
+{
+public:
+ explicit ReentrancySentinel(const char* dllName)
+ {
+ DWORD currentThreadId = GetCurrentThreadId();
+ AutoCriticalSection lock(&sLock);
+ mPreviousDllName = (*sThreadMap)[currentThreadId];
+
+ // If there is a DLL currently being loaded and it has the same name
+ // as the current attempt, we're re-entering.
+ mReentered = mPreviousDllName && !stricmp(mPreviousDllName, dllName);
+ (*sThreadMap)[currentThreadId] = dllName;
+ }
+
+ ~ReentrancySentinel()
+ {
+ DWORD currentThreadId = GetCurrentThreadId();
+ AutoCriticalSection lock(&sLock);
+ (*sThreadMap)[currentThreadId] = mPreviousDllName;
+ }
+
+ bool BailOut() const
+ {
+ return mReentered;
+ };
+
+ static void InitializeStatics()
+ {
+ InitializeCriticalSection(&sLock);
+ sThreadMap = new std::map<DWORD, const char*>;
+ }
+
+private:
+ static std::map<DWORD, const char*>* sThreadMap;
+
+ const char* mPreviousDllName;
+ bool mReentered;
+};
+
+std::map<DWORD, const char*>* ReentrancySentinel::sThreadMap;
+
+/**
+ * This is a linked list of DLLs that have been blocked. It doesn't use
+ * mozilla::LinkedList because this is an append-only list and doesn't need
+ * to be doubly linked.
+ */
+class DllBlockSet
+{
+public:
+ static void Add(const char* name, unsigned long long version);
+
+ // Write the list of blocked DLLs to a file HANDLE. This method is run after
+ // a crash occurs and must therefore not use the heap, etc.
+ static void Write(HANDLE file);
+
+private:
+ DllBlockSet(const char* name, unsigned long long version)
+ : mName(name)
+ , mVersion(version)
+ , mNext(nullptr)
+ {
+ }
+
+ const char* mName; // points into the sWindowsDllBlocklist string
+ unsigned long long mVersion;
+ DllBlockSet* mNext;
+
+ static DllBlockSet* gFirst;
+};
+
+DllBlockSet* DllBlockSet::gFirst;
+
+void
+DllBlockSet::Add(const char* name, unsigned long long version)
+{
+ AutoCriticalSection lock(&sLock);
+ for (DllBlockSet* b = gFirst; b; b = b->mNext) {
+ if (0 == strcmp(b->mName, name) && b->mVersion == version) {
+ return;
+ }
+ }
+ // Not already present
+ DllBlockSet* n = new DllBlockSet(name, version);
+ n->mNext = gFirst;
+ gFirst = n;
+}
+
+void
+DllBlockSet::Write(HANDLE file)
+{
+ // It would be nicer to use AutoCriticalSection here. However, its destructor
+ // might not run if an exception occurs, in which case we would never leave
+ // the critical section. (MSVC warns about this possibility.) So we
+ // enter and leave manually.
+ ::EnterCriticalSection(&sLock);
+
+ // Because this method is called after a crash occurs, and uses heap memory,
+ // protect this entire block with a structured exception handler.
+ MOZ_SEH_TRY {
+ DWORD nBytes;
+ for (DllBlockSet* b = gFirst; b; b = b->mNext) {
+ // write name[,v.v.v.v];
+ WriteFile(file, b->mName, strlen(b->mName), &nBytes, nullptr);
+ if (b->mVersion != -1) {
+ WriteFile(file, ",", 1, &nBytes, nullptr);
+ uint16_t parts[4];
+ parts[0] = b->mVersion >> 48;
+ parts[1] = (b->mVersion >> 32) & 0xFFFF;
+ parts[2] = (b->mVersion >> 16) & 0xFFFF;
+ parts[3] = b->mVersion & 0xFFFF;
+ for (int p = 0; p < 4; ++p) {
+ char buf[32];
+ ltoa(parts[p], buf, 10);
+ WriteFile(file, buf, strlen(buf), &nBytes, nullptr);
+ if (p != 3) {
+ WriteFile(file, ".", 1, &nBytes, nullptr);
+ }
+ }
+ }
+ WriteFile(file, ";", 1, &nBytes, nullptr);
+ }
+ }
+ MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { }
+
+ ::LeaveCriticalSection(&sLock);
+}
+
+static UniquePtr<wchar_t[]>
+getFullPath (PWCHAR filePath, wchar_t* fname)
+{
+ // In Windows 8, the first parameter seems to be used for more than just the
+ // path name. For example, its numerical value can be 1. Passing a non-valid
+ // pointer to SearchPathW will cause a crash, so we need to check to see if we
+ // are handed a valid pointer, and otherwise just pass nullptr to SearchPathW.
+ PWCHAR sanitizedFilePath = nullptr;
+ if ((uintptr_t(filePath) >= 65536) && ((uintptr_t(filePath) & 1) == 0)) {
+ sanitizedFilePath = filePath;
+ }
+
+ // figure out the length of the string that we need
+ DWORD pathlen = SearchPathW(sanitizedFilePath, fname, L".dll", 0, nullptr,
+ nullptr);
+ if (pathlen == 0) {
+ return nullptr;
+ }
+
+ auto full_fname = MakeUnique<wchar_t[]>(pathlen+1);
+ if (!full_fname) {
+ // couldn't allocate memory?
+ return nullptr;
+ }
+
+ // now actually grab it
+ SearchPathW(sanitizedFilePath, fname, L".dll", pathlen + 1, full_fname.get(),
+ nullptr);
+ return full_fname;
+}
+
+// No builtin function to find the last character matching a set
+static wchar_t* lastslash(wchar_t* s, int len)
+{
+ for (wchar_t* c = s + len - 1; c >= s; --c) {
+ if (*c == L'\\' || *c == L'/') {
+ return c;
+ }
+ }
+ return nullptr;
+}
+
+static NTSTATUS NTAPI
+patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle)
+{
+ // We have UCS2 (UTF16?), we want ASCII, but we also just want the filename portion
+#define DLLNAME_MAX 128
+ char dllName[DLLNAME_MAX+1];
+ wchar_t *dll_part;
+ char *dot;
+ DllBlockInfo *info;
+
+ int len = moduleFileName->Length / 2;
+ wchar_t *fname = moduleFileName->Buffer;
+ UniquePtr<wchar_t[]> full_fname;
+
+ // The filename isn't guaranteed to be null terminated, but in practice
+ // it always will be; ensure that this is so, and bail if not.
+ // This is done instead of the more robust approach because of bug 527122,
+ // where lots of weird things were happening when we tried to make a copy.
+ if (moduleFileName->MaximumLength < moduleFileName->Length+2 ||
+ fname[len] != 0)
+ {
+#ifdef DEBUG
+ printf_stderr("LdrLoadDll: non-null terminated string found!\n");
+#endif
+ goto continue_loading;
+ }
+
+ dll_part = lastslash(fname, len);
+ if (dll_part) {
+ dll_part = dll_part + 1;
+ len -= dll_part - fname;
+ } else {
+ dll_part = fname;
+ }
+
+#ifdef DEBUG_very_verbose
+ printf_stderr("LdrLoadDll: dll_part '%S' %d\n", dll_part, len);
+#endif
+
+ // if it's too long, then, we assume we won't want to block it,
+ // since DLLNAME_MAX should be at least long enough to hold the longest
+ // entry in our blocklist.
+ if (len > DLLNAME_MAX) {
+#ifdef DEBUG
+ printf_stderr("LdrLoadDll: len too long! %d\n", len);
+#endif
+ goto continue_loading;
+ }
+
+ // copy over to our char byte buffer, lowercasing ASCII as we go
+ for (int i = 0; i < len; i++) {
+ wchar_t c = dll_part[i];
+
+ if (c > 0x7f) {
+ // welp, it's not ascii; if we need to add non-ascii things to
+ // our blocklist, we'll have to remove this limitation.
+ goto continue_loading;
+ }
+
+ // ensure that dll name is all lowercase
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+
+ dllName[i] = (char) c;
+ }
+
+ dllName[len] = 0;
+
+#ifdef DEBUG_very_verbose
+ printf_stderr("LdrLoadDll: dll name '%s'\n", dllName);
+#endif
+
+ // Block a suspicious binary that uses various 12-digit hex strings
+ // e.g. MovieMode.48CA2AEFA22D.dll (bug 973138)
+ dot = strchr(dllName, '.');
+ if (dot && (strchr(dot+1, '.') == dot+13)) {
+ char * end = nullptr;
+ _strtoui64(dot+1, &end, 16);
+ if (end == dot+13) {
+ return STATUS_DLL_NOT_FOUND;
+ }
+ }
+ // Block binaries where the filename is at least 16 hex digits
+ if (dot && ((dot - dllName) >= 16)) {
+ char * current = dllName;
+ while (current < dot && isxdigit(*current)) {
+ current++;
+ }
+ if (current == dot) {
+ return STATUS_DLL_NOT_FOUND;
+ }
+ }
+
+ // then compare to everything on the blocklist
+ info = &sWindowsDllBlocklist[0];
+ while (info->name) {
+ if (strcmp(info->name, dllName) == 0)
+ break;
+
+ info++;
+ }
+
+ if (info->name) {
+ bool load_ok = false;
+
+#ifdef DEBUG_very_verbose
+ printf_stderr("LdrLoadDll: info->name: '%s'\n", info->name);
+#endif
+
+ if ((info->flags == DllBlockInfo::BLOCK_WIN8PLUS_ONLY) &&
+ !IsWin8OrLater()) {
+ goto continue_loading;
+ }
+
+ if ((info->flags == DllBlockInfo::BLOCK_XP_ONLY) &&
+ IsWin2003OrLater()) {
+ goto continue_loading;
+ }
+
+ unsigned long long fVersion = ALL_VERSIONS;
+
+ if (info->maxVersion != ALL_VERSIONS) {
+ ReentrancySentinel sentinel(dllName);
+ if (sentinel.BailOut()) {
+ goto continue_loading;
+ }
+
+ full_fname = getFullPath(filePath, fname);
+ if (!full_fname) {
+ // uh, we couldn't find the DLL at all, so...
+ printf_stderr("LdrLoadDll: Blocking load of '%s' (SearchPathW didn't find it?)\n", dllName);
+ return STATUS_DLL_NOT_FOUND;
+ }
+
+ if (info->flags & DllBlockInfo::USE_TIMESTAMP) {
+ fVersion = GetTimestamp(full_fname.get());
+ if (fVersion > info->maxVersion) {
+ load_ok = true;
+ }
+ } else {
+ DWORD zero;
+ DWORD infoSize = GetFileVersionInfoSizeW(full_fname.get(), &zero);
+
+ // If we failed to get the version information, we block.
+
+ if (infoSize != 0) {
+ auto infoData = MakeUnique<unsigned char[]>(infoSize);
+ VS_FIXEDFILEINFO *vInfo;
+ UINT vInfoLen;
+
+ if (GetFileVersionInfoW(full_fname.get(), 0, infoSize, infoData.get()) &&
+ VerQueryValueW(infoData.get(), L"\\", (LPVOID*) &vInfo, &vInfoLen))
+ {
+ fVersion =
+ ((unsigned long long)vInfo->dwFileVersionMS) << 32 |
+ ((unsigned long long)vInfo->dwFileVersionLS);
+
+ // finally do the version check, and if it's greater than our block
+ // version, keep loading
+ if (fVersion > info->maxVersion)
+ load_ok = true;
+ }
+ }
+ }
+ }
+
+ if (!load_ok) {
+ printf_stderr("LdrLoadDll: Blocking load of '%s' -- see http://www.mozilla.com/en-US/blocklist/\n", dllName);
+ DllBlockSet::Add(info->name, fVersion);
+ return STATUS_DLL_NOT_FOUND;
+ }
+ }
+
+continue_loading:
+#ifdef DEBUG_very_verbose
+ printf_stderr("LdrLoadDll: continuing load... ('%S')\n", moduleFileName->Buffer);
+#endif
+
+ if (GetCurrentThreadId() == sThreadLoadingXPCOMModule) {
+ // Check to ensure that the DLL has ASLR.
+ full_fname = getFullPath(filePath, fname);
+ if (!full_fname) {
+ // uh, we couldn't find the DLL at all, so...
+ printf_stderr("LdrLoadDll: Blocking load of '%s' (SearchPathW didn't find it?)\n", dllName);
+ return STATUS_DLL_NOT_FOUND;
+ }
+
+ if (IsVistaOrLater() && !CheckASLR(full_fname.get())) {
+ printf_stderr("LdrLoadDll: Blocking load of '%s'. XPCOM components must support ASLR.\n", dllName);
+ return STATUS_DLL_NOT_FOUND;
+ }
+ }
+
+ return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
+}
+
+WindowsDllInterceptor NtDllIntercept;
+
+} // namespace
+
+MFBT_API void
+DllBlocklist_Initialize()
+{
+ if (sBlocklistInitAttempted) {
+ return;
+ }
+ sBlocklistInitAttempted = true;
+
+ if (GetModuleHandleA("user32.dll")) {
+ sUser32BeforeBlocklist = true;
+ }
+
+ NtDllIntercept.Init("ntdll.dll");
+
+ ReentrancySentinel::InitializeStatics();
+
+ // We specifically use a detour, because there are cases where external
+ // code also tries to hook LdrLoadDll, and doesn't know how to relocate our
+ // nop space patches. (Bug 951827)
+ bool ok = NtDllIntercept.AddDetour("LdrLoadDll", reinterpret_cast<intptr_t>(patched_LdrLoadDll), (void**) &stub_LdrLoadDll);
+
+ if (!ok) {
+ sBlocklistInitFailed = true;
+#ifdef DEBUG
+ printf_stderr ("LdrLoadDll hook failed, no dll blocklisting active\n");
+#endif
+ }
+}
+
+MFBT_API void
+DllBlocklist_SetInXPCOMLoadOnMainThread(bool inXPCOMLoadOnMainThread)
+{
+ if (inXPCOMLoadOnMainThread) {
+ MOZ_ASSERT(sThreadLoadingXPCOMModule == 0, "Only one thread should be doing this");
+ sThreadLoadingXPCOMModule = GetCurrentThreadId();
+ } else {
+ sThreadLoadingXPCOMModule = 0;
+ }
+}
+
+MFBT_API void
+DllBlocklist_WriteNotes(HANDLE file)
+{
+ DWORD nBytes;
+
+ WriteFile(file, kBlockedDllsParameter, kBlockedDllsParameterLen, &nBytes, nullptr);
+ DllBlockSet::Write(file);
+ WriteFile(file, "\n", 1, &nBytes, nullptr);
+
+ if (sBlocklistInitFailed) {
+ WriteFile(file, kBlocklistInitFailedParameter,
+ kBlocklistInitFailedParameterLen, &nBytes, nullptr);
+ }
+
+ if (sUser32BeforeBlocklist) {
+ WriteFile(file, kUser32BeforeBlocklistParameter,
+ kUser32BeforeBlocklistParameterLen, &nBytes, nullptr);
+ }
+}
+
+MFBT_API bool
+DllBlocklist_CheckStatus()
+{
+ if (sBlocklistInitFailed || sUser32BeforeBlocklist)
+ return false;
+ return true;
+}
diff --git a/mozglue/build/WindowsDllBlocklist.h b/mozglue/build/WindowsDllBlocklist.h
new file mode 100644
index 000000000..5afe6b8ce
--- /dev/null
+++ b/mozglue/build/WindowsDllBlocklist.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_windowsdllblocklist_h
+#define mozilla_windowsdllblocklist_h
+
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+
+#include <windows.h>
+#include "mozilla/GuardObjects.h"
+#include "mozilla/Attributes.h"
+
+#define HAS_DLL_BLOCKLIST
+
+MFBT_API void DllBlocklist_Initialize();
+MFBT_API void DllBlocklist_SetInXPCOMLoadOnMainThread(bool inXPCOMLoadOnMainThread);
+MFBT_API void DllBlocklist_WriteNotes(HANDLE file);
+MFBT_API bool DllBlocklist_CheckStatus();
+
+class MOZ_RAII AutoSetXPCOMLoadOnMainThread
+{
+ public:
+ AutoSetXPCOMLoadOnMainThread(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ DllBlocklist_SetInXPCOMLoadOnMainThread(true);
+ }
+
+ ~AutoSetXPCOMLoadOnMainThread() {
+ DllBlocklist_SetInXPCOMLoadOnMainThread(false);
+ }
+
+ private:
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+#endif // defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+#endif // mozilla_windowsdllblocklist_h
diff --git a/mozglue/build/arm-eabi-filter b/mozglue/build/arm-eabi-filter
new file mode 100644
index 000000000..401454ee8
--- /dev/null
+++ b/mozglue/build/arm-eabi-filter
@@ -0,0 +1,4 @@
+{
+ local:
+ __aeabi*;
+};
diff --git a/mozglue/build/arm.cpp b/mozglue/build/arm.cpp
new file mode 100644
index 000000000..74b856a8f
--- /dev/null
+++ b/mozglue/build/arm.cpp
@@ -0,0 +1,147 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* compile-time and runtime tests for whether to use various ARM extensions */
+
+#include "arm.h"
+
+#if defined(MOZILLA_ARM_HAVE_CPUID_DETECTION)
+
+// arm.h has parallel #ifs which declare MOZILLA_ARM_HAVE_CPUID_DETECTION.
+// We don't check it here so that we get compile errors if it's defined, but
+// we don't compile one of these detection methods. The detection code here is
+// based on the CPU detection in libtheora.
+
+# if defined(__linux__) || defined(ANDROID)
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+
+enum{
+ MOZILLA_HAS_EDSP_FLAG=1,
+ MOZILLA_HAS_ARMV6_FLAG=2,
+ MOZILLA_HAS_ARMV7_FLAG=4,
+ MOZILLA_HAS_NEON_FLAG=8
+};
+
+static unsigned
+get_arm_cpu_flags(void)
+{
+ unsigned flags;
+ FILE *fin;
+ bool armv6_processor = false;
+ flags = 0;
+ /*Reading /proc/self/auxv would be easier, but that doesn't work reliably on
+ Android. This also means that detection will fail in Scratchbox, which is
+ desirable, as NEON does not work in the qemu shipped with the Maemo 5 SDK.
+ I don't know if /proc/self/auxv would do any better in that case, anyway,
+ or if it would return random flags from the host CPU.*/
+ fin = fopen ("/proc/cpuinfo","r");
+ if (fin != nullptr)
+ {
+ /*512 should be enough for anybody (it's even enough for all the flags that
+ x86 has accumulated... so far).*/
+ char buf[512];
+ while (fgets(buf, 511, fin) != nullptr)
+ {
+ if (memcmp(buf, "Features", 8) == 0)
+ {
+ char *p;
+ p = strstr(buf, " edsp");
+ if (p != nullptr && (p[5] == ' ' || p[5] == '\n'))
+ flags |= MOZILLA_HAS_EDSP_FLAG;
+ p = strstr(buf, " neon");
+ if( p != nullptr && (p[5] == ' ' || p[5] == '\n'))
+ flags |= MOZILLA_HAS_NEON_FLAG;
+ }
+ if (memcmp(buf, "CPU architecture:", 17) == 0)
+ {
+ int version;
+ version = atoi(buf + 17);
+ if (version >= 6)
+ flags |= MOZILLA_HAS_ARMV6_FLAG;
+ if (version >= 7)
+ flags |= MOZILLA_HAS_ARMV7_FLAG;
+ }
+ /* media/webrtc/trunk/src/system_wrappers/source/cpu_features_arm.c
+ * Unfortunately, it seems that certain ARMv6-based CPUs
+ * report an incorrect architecture number of 7!
+ *
+ * We try to correct this by looking at the 'elf_format'
+ * field reported by the 'Processor' field, which is of the
+ * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
+ * an ARMv6-one.
+ */
+ if (memcmp(buf, "Processor\t:", 11) == 0) {
+ if (strstr(buf, "(v6l)") != 0) {
+ armv6_processor = true;
+ }
+ }
+ }
+ fclose(fin);
+ }
+ if (armv6_processor) {
+ // ARMv6 pretending to be ARMv7? clear flag
+ if (flags & MOZILLA_HAS_ARMV7_FLAG) {
+ flags &= ~MOZILLA_HAS_ARMV7_FLAG;
+ }
+ }
+ return flags;
+}
+
+// Cache a local copy so we only have to read /proc/cpuinfo once.
+static unsigned arm_cpu_flags = get_arm_cpu_flags();
+
+# if !defined(MOZILLA_PRESUME_EDSP)
+static bool
+check_edsp(void)
+{
+ return (arm_cpu_flags & MOZILLA_HAS_EDSP_FLAG) != 0;
+}
+# endif
+
+# if !defined(MOZILLA_PRESUME_ARMV6)
+static bool
+check_armv6(void)
+{
+ return (arm_cpu_flags & MOZILLA_HAS_ARMV6_FLAG) != 0;
+}
+# endif
+
+# if !defined(MOZILLA_PRESUME_ARMV7)
+static bool
+check_armv7(void)
+{
+ return (arm_cpu_flags & MOZILLA_HAS_ARMV7_FLAG) != 0;
+}
+# endif
+
+# if !defined(MOZILLA_PRESUME_NEON)
+static bool
+check_neon(void)
+{
+ return (arm_cpu_flags & MOZILLA_HAS_NEON_FLAG) != 0;
+}
+# endif
+
+# endif // defined(__linux__) || defined(ANDROID)
+
+namespace mozilla {
+ namespace arm_private {
+# if !defined(MOZILLA_PRESUME_EDSP)
+ bool edsp_enabled = check_edsp();
+# endif
+# if !defined(MOZILLA_PRESUME_ARMV6)
+ bool armv6_enabled = check_armv6();
+# endif
+# if !defined(MOZILLA_PRESUME_ARMV7)
+ bool armv7_enabled = check_armv7();
+# endif
+# if !defined(MOZILLA_PRESUME_NEON)
+ bool neon_enabled = check_neon();
+# endif
+ } // namespace arm_private
+} // namespace mozilla
+
+#endif // MOZILLA_ARM_HAVE_CPUID_DETECTION
diff --git a/mozglue/build/arm.h b/mozglue/build/arm.h
new file mode 100644
index 000000000..e3379f67b
--- /dev/null
+++ b/mozglue/build/arm.h
@@ -0,0 +1,146 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* compile-time and runtime tests for whether to use SSE instructions */
+
+#ifndef mozilla_arm_h_
+#define mozilla_arm_h_
+
+// for definition of MFBT_DATA
+#include "mozilla/Types.h"
+
+/* This is patterned after SSE.h, but provides ARMv5E, ARMv6, and NEON
+ detection. For reasons similar to the SSE code, code using NEON (even just
+ in inline asm) needs to be in a separate compilation unit from the regular
+ code, because it requires an ".fpu neon" directive which can't be undone.
+ ARMv5E and ARMv6 code may also require an .arch directive, since by default
+ the assembler refuses to generate code for opcodes outside of its current
+ .arch setting.
+
+ TODO: Add Thumb, Thumb2, VFP, iwMMX, etc. detection, if we need it. */
+
+#if defined(__GNUC__) && defined(__arm__)
+
+# define MOZILLA_ARM_ARCH 3
+
+# if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) \
+ || defined(_ARM_ARCH_4)
+# undef MOZILLA_ARM_ARCH
+# define MOZILLA_ARM_ARCH 4
+# endif
+
+# if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
+ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+ || defined(__ARM_ARCH_5TEJ__) || defined(_ARM_ARCH_5)
+# undef MOZILLA_ARM_ARCH
+# define MOZILLA_ARM_ARCH 5
+# endif
+
+# if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \
+ || defined(__ARM_ARCH_6M__) || defined(_ARM_ARCH_6)
+# undef MOZILLA_ARM_ARCH
+# define MOZILLA_ARM_ARCH 6
+# endif
+
+# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \
+ || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \
+ || defined(__ARM_ARCH_7EM__) || defined(_ARM_ARCH_7)
+# undef MOZILLA_ARM_ARCH
+# define MOZILLA_ARM_ARCH 7
+# endif
+
+
+# ifdef __GNUC__
+# define MOZILLA_MAY_SUPPORT_EDSP 1
+
+# if defined(HAVE_ARM_SIMD)
+# define MOZILLA_MAY_SUPPORT_ARMV6 1
+# endif
+
+# if defined(HAVE_ARM_NEON)
+# define MOZILLA_MAY_SUPPORT_NEON 1
+# endif
+
+# if defined(HAVE_ARM_SIMD)
+# define MOZILLA_MAY_SUPPORT_ARMV7 1
+# endif
+# endif
+
+ // When using -mfpu=neon, gcc generates neon instructions.
+
+# if defined(__ARM_NEON__)
+# define MOZILLA_PRESUME_NEON 1
+# endif
+
+ // Currently we only have CPU detection for Linux via /proc/cpuinfo
+# if defined(__linux__) || defined(ANDROID)
+# define MOZILLA_ARM_HAVE_CPUID_DETECTION 1
+# endif
+
+#endif
+
+namespace mozilla {
+
+ namespace arm_private {
+#if defined(MOZILLA_ARM_HAVE_CPUID_DETECTION)
+#if !defined(MOZILLA_PRESUME_EDSP)
+ extern bool MFBT_DATA edsp_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_ARMV6)
+ extern bool MFBT_DATA armv6_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_ARMV7)
+ extern bool MFBT_DATA armv7_enabled;
+#endif
+#if !defined(MOZILLA_PRESUME_NEON)
+ extern bool MFBT_DATA neon_enabled;
+#endif
+#endif
+ } // namespace arm_private
+
+#if defined(MOZILLA_PRESUME_EDSP)
+# define MOZILLA_MAY_SUPPORT_EDSP 1
+ inline bool supports_edsp() { return true; }
+#elif defined(MOZILLA_MAY_SUPPORT_EDSP) \
+ && defined(MOZILLA_ARM_HAVE_CPUID_DETECTION)
+ inline bool supports_edsp() { return arm_private::edsp_enabled; }
+#else
+ inline bool supports_edsp() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_ARMV6)
+# define MOZILLA_MAY_SUPPORT_ARMV6 1
+ inline bool supports_armv6() { return true; }
+#elif defined(MOZILLA_MAY_SUPPORT_ARMV6) \
+ && defined(MOZILLA_ARM_HAVE_CPUID_DETECTION)
+ inline bool supports_armv6() { return arm_private::armv6_enabled; }
+#else
+ inline bool supports_armv6() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_ARMV7)
+# define MOZILLA_MAY_SUPPORT_ARMV7 1
+ inline bool supports_armv7() { return true; }
+#elif defined(MOZILLA_MAY_SUPPORT_ARMV7) \
+ && defined(MOZILLA_ARM_HAVE_CPUID_DETECTION)
+ inline bool supports_armv7() { return arm_private::armv7_enabled; }
+#else
+ inline bool supports_armv7() { return false; }
+#endif
+
+#if defined(MOZILLA_PRESUME_NEON)
+# define MOZILLA_MAY_SUPPORT_NEON 1
+ inline bool supports_neon() { return true; }
+#elif defined(MOZILLA_MAY_SUPPORT_NEON) \
+ && defined(MOZILLA_ARM_HAVE_CPUID_DETECTION)
+ inline bool supports_neon() { return arm_private::neon_enabled; }
+#else
+ inline bool supports_neon() { return false; }
+#endif
+
+} // namespace mozilla
+
+#endif /* !defined(mozilla_arm_h_) */
diff --git a/mozglue/build/cpuacct.c b/mozglue/build/cpuacct.c
new file mode 100644
index 000000000..ce7d98eda
--- /dev/null
+++ b/mozglue/build/cpuacct.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include "cpuacct.h"
+
+int cpuacct_add(uid_t uid)
+{
+ int count;
+ int fd;
+ char buf[80];
+
+ count = snprintf(buf, sizeof(buf), "/acct/uid/%d/tasks", uid);
+ fd = open(buf, O_RDWR|O_CREAT|O_TRUNC|O_SYNC);
+ if (fd < 0) {
+ /* Note: sizeof("tasks") returns 6, which includes the NULL char */
+ buf[count - sizeof("tasks")] = 0;
+ if (mkdir(buf, 0775) < 0)
+ return -errno;
+
+ /* Note: sizeof("tasks") returns 6, which includes the NULL char */
+ buf[count - sizeof("tasks")] = '/';
+ fd = open(buf, O_RDWR|O_CREAT|O_TRUNC|O_SYNC);
+ }
+ if (fd < 0)
+ return -errno;
+
+ write(fd, "0", 2);
+ if (close(fd))
+ return -errno;
+
+ return 0;
+}
diff --git a/mozglue/build/cpuacct.h b/mozglue/build/cpuacct.h
new file mode 100644
index 000000000..8e24c8cc8
--- /dev/null
+++ b/mozglue/build/cpuacct.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _BIONIC_CPUACCT_H
+#define _BIONIC_CPUACCT_H
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+__BEGIN_DECLS
+
+extern int cpuacct_add(uid_t uid);
+
+__END_DECLS
+
+#endif /* _BIONIC_CPUACCT_H */
diff --git a/mozglue/build/dummy.cpp b/mozglue/build/dummy.cpp
new file mode 100644
index 000000000..47866547f
--- /dev/null
+++ b/mozglue/build/dummy.cpp
@@ -0,0 +1,6 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+void _dummy(void) {
+}
diff --git a/mozglue/build/mips.cpp b/mozglue/build/mips.cpp
new file mode 100644
index 000000000..6a015db8a
--- /dev/null
+++ b/mozglue/build/mips.cpp
@@ -0,0 +1,47 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* compile-time and runtime tests for whether to use MIPS-specific extensions */
+
+#include "mips.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+enum{
+ MIPS_FLAG_LOONGSON3 = 1,
+};
+
+static unsigned
+get_mips_cpu_flags(void)
+{
+ unsigned flags = 0;
+ FILE *fin;
+
+ fin = fopen("/proc/cpuinfo","r");
+ if (fin != nullptr) {
+ char buf[1024];
+ memset(buf, 0, sizeof(buf));
+ fread(buf, sizeof(char), sizeof(buf) - 1, fin);
+ fclose(fin);
+ if (strstr(buf, "Loongson-3"))
+ flags |= MIPS_FLAG_LOONGSON3;
+ }
+ return flags;
+}
+
+static bool
+check_loongson3(void)
+{
+ // Cache a local copy so we only have to read /proc/cpuinfo once.
+ static unsigned mips_cpu_flags = get_mips_cpu_flags();
+ return (mips_cpu_flags & MIPS_FLAG_LOONGSON3) != 0;
+}
+
+namespace mozilla {
+ namespace mips_private {
+ bool isLoongson3 = check_loongson3();
+ } // namespace mips_private
+} // namespace mozilla
diff --git a/mozglue/build/mips.h b/mozglue/build/mips.h
new file mode 100644
index 000000000..ff31cbc87
--- /dev/null
+++ b/mozglue/build/mips.h
@@ -0,0 +1,29 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* compile-time and runtime tests for whether to use MIPS-specific extensions */
+
+#ifndef mozilla_mips_h_
+#define mozilla_mips_h_
+
+// for definition of MFBT_DATA
+#include "mozilla/Types.h"
+
+namespace mozilla {
+
+ namespace mips_private {
+ extern bool MFBT_DATA isLoongson3;
+ } // namespace mips_private
+
+ inline bool supports_mmi() {
+#ifdef __mips__
+ return mips_private::isLoongson3;
+#else
+ return false;
+#endif
+ }
+
+} // namespace mozilla
+
+#endif /* !defined(mozilla_mips_h_) */
diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build
new file mode 100644
index 000000000..d28974778
--- /dev/null
+++ b/mozglue/build/moz.build
@@ -0,0 +1,108 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Build mozglue as a shared lib on Windows, OSX and Android.
+# If this is ever changed, update MOZ_SHARED_MOZGLUE in browser/installer/Makefile.in
+if CONFIG['OS_TARGET'] in ('WINNT', 'Darwin', 'Android'):
+ SharedLibrary('mozglue')
+else:
+ Library('mozglue')
+
+SDK_LIBRARY = True
+
+if CONFIG['OS_TARGET'] == 'Android':
+ SOURCES += [
+ 'BionicGlue.cpp',
+ ]
+
+if CONFIG['MOZ_ASAN']:
+ SOURCES += [
+ 'AsanOptions.cpp',
+ ]
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+ DEFFILE = 'mozglue.def'
+ # We'll break the DLL blocklist if we immediately load user32.dll
+ DELAYLOAD_DLLS += [
+ 'user32.dll',
+ ]
+
+if not CONFIG['JS_STANDALONE']:
+
+ if CONFIG['MOZ_MEMORY'] and (CONFIG['MOZ_SYSTEM_JEMALLOC'] or FORCE_SHARED_LIB):
+ pass
+ # TODO: SHARED_LIBRARY_LIBS go here
+ else:
+ # Temporary, until bug 662814 lands
+ NO_VISIBILITY_FLAGS = True
+ SOURCES += [
+ 'dummy.cpp',
+ ]
+
+ if CONFIG['OS_TARGET'] == 'WINNT':
+ LOCAL_INCLUDES += [
+ '/memory/build',
+ ]
+ SOURCES += [
+ 'WindowsDllBlocklist.cpp',
+ ]
+ DISABLE_STL_WRAPPING = True
+ OS_LIBS += [
+ 'version',
+ ]
+
+ EXPORTS.mozilla += [
+ 'arm.h',
+ 'mips.h',
+ 'SSE.h',
+ 'WindowsDllBlocklist.h',
+ ]
+
+ if CONFIG['CPU_ARCH'].startswith('x86'):
+ SOURCES += [
+ 'SSE.cpp',
+ ]
+
+ if CONFIG['CPU_ARCH'] == 'arm':
+ SOURCES += [
+ 'arm.cpp',
+ ]
+
+ if CONFIG['CPU_ARCH'].startswith('mips'):
+ SOURCES += [
+ 'mips.cpp',
+ ]
+
+ if CONFIG['MOZ_LINKER']:
+ USE_LIBS += [
+ 'zlib',
+ ]
+
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+ SOURCES += [
+ 'cpuacct.c',
+ ]
+
+USE_LIBS += [
+ 'mfbt',
+]
+
+DEFINES['IMPL_MFBT'] = True
+LIBRARY_DEFINES['MOZ_HAS_MOZGLUE'] = True
+
+LDFLAGS += CONFIG['MOZ_GLUE_WRAP_LDFLAGS']
+
+if CONFIG['OS_TARGET'] == 'Darwin':
+ # On OSX 10.10.3, a dead lock happens in some cases involving dynamic
+ # symbol resolution for symbols that jemalloc itself uses. While it
+ # might be possible to find a way to avoid all such symbol resolutions,
+ # it's currently not possible because at the very least there's a call
+ # to pthread_self from tsd_init_check_recursion, which is necessary
+ # because somehow clang doesn't want to accept the __thread keyword
+ # for TLS.
+ LDFLAGS += ['-Wl,-bind_at_load']
+
+DIST_INSTALL = True
diff --git a/mozglue/build/mozglue.def.in b/mozglue/build/mozglue.def.in
new file mode 100644
index 000000000..62eb3caed
--- /dev/null
+++ b/mozglue/build/mozglue.def.in
@@ -0,0 +1,39 @@
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+LIBRARY mozglue.dll
+
+EXPORTS
+#ifdef MOZ_MEMORY
+ ; symbols that are actually useful
+#ifdef MOZ_REPLACE_MALLOC
+ malloc=malloc_impl
+ calloc=calloc_impl
+ realloc=realloc_impl
+ free=free_impl
+ posix_memalign=posix_memalign_impl
+ malloc_usable_size=malloc_usable_size_impl
+ malloc_good_size=malloc_good_size_impl
+ _aligned_free=free_impl
+#else
+ malloc=je_malloc
+ calloc=je_calloc
+ realloc=je_realloc
+ free=je_free
+ posix_memalign=je_posix_memalign
+ malloc_usable_size=je_malloc_usable_size
+ malloc_good_size=je_malloc_good_size
+ _aligned_free=je_free
+#endif
+ _aligned_malloc
+ strndup=wrap_strndup
+ strdup=wrap_strdup
+ _strdup=wrap_strdup
+ wcsdup=wrap_wcsdup
+ _wcsdup=wrap_wcsdup
+ jemalloc_stats
+ jemalloc_free_dirty_pages
+ ; A hack to work around the CRT (see giant comment in Makefile.in)
+ frex=dumb_free_thunk
+#endif
diff --git a/mozglue/build/replace_malloc.mk b/mozglue/build/replace_malloc.mk
new file mode 100644
index 000000000..7f436f2ee
--- /dev/null
+++ b/mozglue/build/replace_malloc.mk
@@ -0,0 +1,32 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ifeq (Darwin_1,$(OS_TARGET)_$(MOZ_REPLACE_MALLOC))
+OS_LDFLAGS += \
+ -Wl,-U,_replace_init \
+ -Wl,-U,_replace_get_bridge \
+ -Wl,-U,_replace_malloc \
+ -Wl,-U,_replace_posix_memalign \
+ -Wl,-U,_replace_aligned_alloc \
+ -Wl,-U,_replace_calloc \
+ -Wl,-U,_replace_realloc \
+ -Wl,-U,_replace_free \
+ -Wl,-U,_replace_memalign \
+ -Wl,-U,_replace_valloc \
+ -Wl,-U,_replace_malloc_usable_size \
+ -Wl,-U,_replace_malloc_good_size \
+ -Wl,-U,_replace_jemalloc_stats \
+ -Wl,-U,_replace_jemalloc_purge_freed_pages \
+ -Wl,-U,_replace_jemalloc_free_dirty_pages \
+ $(NULL)
+
+ifneq ($(MOZ_REPLACE_MALLOC_LINKAGE),compiler support)
+OS_LDFLAGS += -flat_namespace
+endif
+ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library)
+OS_LDFLAGS += -Wl,-weak_library,$(DEPTH)/memory/replace/dummy/$(DLL_PREFIX)dummy_replace_malloc$(DLL_SUFFIX)
+endif
+
+EXTRA_DEPS += $(topsrcdir)/mozglue/build/replace_malloc.mk
+endif