From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- mozglue/build/AsanOptions.cpp | 35 ++ mozglue/build/BionicGlue.cpp | 157 +++++++ mozglue/build/Makefile.in | 23 + mozglue/build/SSE.cpp | 206 +++++++++ mozglue/build/SSE.h | 332 ++++++++++++++ mozglue/build/WindowsDllBlocklist.cpp | 831 ++++++++++++++++++++++++++++++++++ mozglue/build/WindowsDllBlocklist.h | 39 ++ mozglue/build/arm-eabi-filter | 4 + mozglue/build/arm.cpp | 147 ++++++ mozglue/build/arm.h | 146 ++++++ mozglue/build/cpuacct.c | 61 +++ mozglue/build/cpuacct.h | 41 ++ mozglue/build/dummy.cpp | 6 + mozglue/build/mips.cpp | 47 ++ mozglue/build/mips.h | 29 ++ mozglue/build/moz.build | 108 +++++ mozglue/build/mozglue.def.in | 39 ++ mozglue/build/replace_malloc.mk | 32 ++ 18 files changed, 2283 insertions(+) create mode 100644 mozglue/build/AsanOptions.cpp create mode 100644 mozglue/build/BionicGlue.cpp create mode 100644 mozglue/build/Makefile.in create mode 100644 mozglue/build/SSE.cpp create mode 100644 mozglue/build/SSE.h create mode 100644 mozglue/build/WindowsDllBlocklist.cpp create mode 100644 mozglue/build/WindowsDllBlocklist.h create mode 100644 mozglue/build/arm-eabi-filter create mode 100644 mozglue/build/arm.cpp create mode 100644 mozglue/build/arm.h create mode 100644 mozglue/build/cpuacct.c create mode 100644 mozglue/build/cpuacct.h create mode 100644 mozglue/build/dummy.cpp create mode 100644 mozglue/build/mips.cpp create mode 100644 mozglue/build/mips.h create mode 100644 mozglue/build/moz.build create mode 100644 mozglue/build/mozglue.def.in create mode 100644 mozglue/build/replace_malloc.mk (limited to 'mozglue/build') diff --git a/mozglue/build/AsanOptions.cpp b/mozglue/build/AsanOptions.cpp new file mode 100644 index 0000000000..729c61ef31 --- /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 0000000000..208fcce68c --- /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 +#include +#include +#include +#include +#include +#include + +#include "mozilla/Alignment.h" + +#include + +#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 +struct SpecialAllocator: public std::allocator +{ + SpecialAllocator(): bufUsed(false) {} + + inline typename std::allocator::pointer allocate(typename std::allocator::size_type n, const void * = 0) { + if (!bufUsed && n == 1) { + bufUsed = true; + return buf.addr(); + } + return reinterpret_cast(::operator new(sizeof(T) * n)); + } + + inline void deallocate(typename std::allocator::pointer p, typename std::allocator::size_type n) { + if (p == buf.addr()) + bufUsed = false; + else + ::operator delete(p); + } + + template + struct rebind { + typedef SpecialAllocator other; + }; + +private: + mozilla::AlignedStorage2 buf; + bool bufUsed; +}; + +static std::vector > 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 0000000000..1cfa41ea04 --- /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 0000000000..8ad228684c --- /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 +#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64)) +// MSVC 2005 or newer on x86-32 or x86-64 +#include +#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 +// conflicts with on MSVC 2005, and some files want to +// include both SSE.h and . + +#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 0000000000..fe77886409 --- /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 0000000000..a3c6627233 --- /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 +#include +#include + +#pragma warning( push ) +#pragma warning( disable : 4275 4530 ) // See msvc-stl-wrapper.template.h +#include +#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 +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((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 peHeader(map, 0); + if (peHeader) { + RVAMap 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 peHeader(map, 0); + if (peHeader) { + RVAMap 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; + } + +private: + static std::map* sThreadMap; + + const char* mPreviousDllName; + bool mReentered; +}; + +std::map* 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 +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(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 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(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(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 0000000000..5afe6b8cee --- /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 +#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 0000000000..401454ee88 --- /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 0000000000..74b856a8f6 --- /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 +# include +# include + +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 0000000000..e3379f67b0 --- /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 0000000000..ce7d98edac --- /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 +#include +#include +#include +#include +#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 0000000000..8e24c8cc89 --- /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 +#include + +__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 0000000000..47866547ff --- /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 0000000000..6a015db8af --- /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 +#include +#include + +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 0000000000..ff31cbc875 --- /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 0000000000..d289747785 --- /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 0000000000..62eb3caed4 --- /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 0000000000..7f436f2eea --- /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 -- cgit v1.2.3