diff options
author | Timo Teräs <timo.teras@iki.fi> | 2014-04-18 05:03:20 +0000 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2014-04-18 05:03:20 +0000 |
commit | bd38c128ac8e989a66e5873a6c48524eb5c17ae5 (patch) | |
tree | 33b3f108c0f7607b33ef36de511c0d1cd20361ae /main | |
parent | d5c15049c9e4fb66045d5a126258d6417f461a6d (diff) | |
download | aports-bd38c128ac8e989a66e5873a6c48524eb5c17ae5.tar.bz2 aports-bd38c128ac8e989a66e5873a6c48524eb5c17ae5.tar.xz |
main/xulrunner: fix arm build on grsec
the kuser_helpers are disabled by default on grsec. we target
arm6+ so make arm atomics be inline assembly always.
Diffstat (limited to 'main')
-rw-r--r-- | main/xulrunner/APKBUILD | 4 | ||||
-rw-r--r-- | main/xulrunner/fix-arm-atomics-grsec.patch | 342 |
2 files changed, 346 insertions, 0 deletions
diff --git a/main/xulrunner/APKBUILD b/main/xulrunner/APKBUILD index ae65bff8cc..b3dbee45c2 100644 --- a/main/xulrunner/APKBUILD +++ b/main/xulrunner/APKBUILD @@ -54,6 +54,7 @@ source="ftp://ftp.mozilla.org/pub/firefox/releases/$pkgver/source/firefox-$pkgve getchar.patch stat.patch moz-libc-filename.patch + fix-arm-atomics-grsec.patch fix-ipc.patch fix-media.patch @@ -137,6 +138,7 @@ f2e5631a1b7a338c2b80b038630647c8 uclibc-malloc_usable_size.patch 507742325de8687529e4e81e31132ddf getchar.patch d9a2245b93a7f5855ee029b5fa44e4e9 stat.patch 21b2f7d8718acef5804d620a6f6335c0 moz-libc-filename.patch +b18bd948aae828e5c8f5f63e440c96d6 fix-arm-atomics-grsec.patch 38a9c0d5be155164d50a956ac131d991 fix-ipc.patch 960d56439a375998ce4e4597bf245375 fix-media.patch e1d52fd12bfcf3142028a9ab547cf8d1 fix-netwerk.patch @@ -153,6 +155,7 @@ sha256sums="2ffd0484e7eab52166b851681878a86d54223a6764c756721430fae8e1599628 fi d14357bf44f702d94b8d3ed79bdf81f6271370745c1ac8fa83522bd98be4adc4 getchar.patch a0f8a0fa9977ee43f3853b6c6bf5a506fdfabdfa32b4279e0ac3d7a3078f34cc stat.patch c3ff0cfd53393211d1026cfe1fab02f195a1cd67eac63c25b132c05a157f5391 moz-libc-filename.patch +ff7cb3c9c4712e0517a6f11e3bf08e9b0d13dbe6384930bdc7f55b1ceed039b5 fix-arm-atomics-grsec.patch 059a69ff0dbceeaa5bbb1446aa4233bc578a047fcad22c0efa27dc64bbd72980 fix-ipc.patch d582712c28a26679d728d21d2ef8964d119182edaf580a948f57a9e808ccc5cf fix-media.patch 0cbb512c4526f0881253a38f1cc79061fba0fe6a0d8b321fb506be190a32e571 fix-netwerk.patch @@ -169,6 +172,7 @@ a74d08b978df2f836b7905fff497304fa189fda22ca070a25b5d4be6e764aa74094a08359dc9a560 18f0696bf4d032c83041110b83ae6531b48474a778fc1deade3b06ba2ae1bfcc9891059287bfb78317c2f5ddc88f5b7ce957312acdb63d4902a57e0b40eb6520 getchar.patch 1a8754830dbbf5432a611504c957c4ff24fdc31dc1a5ee7cdd4240bc5c084baa26a24f18527ff398ec81e56a36aee31732138243cf22a6bab89703656ff463e7 stat.patch 672560d330c55fbfc3d764264efe214503e6da69ef6f295ddfa4923334abcb57dd43988ec8ac67f370fff1083c9a03d6a57a71fcc0a3811ab1231d6ba25806f5 moz-libc-filename.patch +4311464ae52b6d2e2b02c789c6d5fca9b3c211888a983aa609a62c2f2554516fea735ea90673387c69b38a30aa8453ed79faa44b5163df4293880d40df676b2d fix-arm-atomics-grsec.patch 3f360d4231355c268fc52e0fedbce5c4f73ad8d60d9424af8641733c0ae181e6226056e605f0d6653b729a9c8e4abe97a9fb2face25938651a7498d5753cea8b fix-ipc.patch 58e0e7c1c368530b58aa143be0403d733c4b82cc1a9964c925278e5eff147b2ec2c8c34a6cb217387cb7e9f2ca13c2e299745015edaac510704963282dc68e79 fix-media.patch 38ebf7ae81d4b6dac0b6840a64f86759fc10e4a7ef26f1ebdc2b7c8d4aab3f95ddcb204a743b307e5dad0cd6c04b278c2311b1ac599e7bb287092c552ed26a51 fix-netwerk.patch diff --git a/main/xulrunner/fix-arm-atomics-grsec.patch b/main/xulrunner/fix-arm-atomics-grsec.patch new file mode 100644 index 0000000000..5524b2aa73 --- /dev/null +++ b/main/xulrunner/fix-arm-atomics-grsec.patch @@ -0,0 +1,342 @@ +--- mozilla-release/ipc/chromium/src/base/atomicops_internals_arm_gcc.h.orig ++++ mozilla-release/ipc/chromium/src/base/atomicops_internals_arm_gcc.h +@@ -1,8 +1,31 @@ +-// Copyright (c) 2009 The Chromium Authors. All rights reserved. +-// Use of this source code is governed by a BSD-style license that can be +-// found in the LICENSE file. ++// Copyright 2010 the V8 project authors. 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. ++// * Neither the name of Google Inc. nor the names of its ++// contributors may be used to endorse or promote products derived ++// from this software without specific prior written permission. ++// ++// 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. + +-// This file is an internal atomic implementation, use base/atomicops.h instead. ++// This file is an internal atomic implementation, use atomicops.h instead. + // + // LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears. + +@@ -12,43 +35,194 @@ + namespace base { + namespace subtle { + +-// 0xffff0fc0 is the hard coded address of a function provided by +-// the kernel which implements an atomic compare-exchange. On older +-// ARM architecture revisions (pre-v6) this may be implemented using +-// a syscall. This address is stable, and in active use (hard coded) +-// by at least glibc-2.7 and the Android C library. +-typedef Atomic32 (*LinuxKernelCmpxchgFunc)(Atomic32 old_value, +- Atomic32 new_value, +- volatile Atomic32* ptr); +-LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak)) = +- (LinuxKernelCmpxchgFunc) 0xffff0fc0; ++// Memory barriers on ARM are funky, but the kernel is here to help: ++// ++// * ARMv5 didn't support SMP, there is no memory barrier instruction at ++// all on this architecture, or when targeting its machine code. ++// ++// * Some ARMv6 CPUs support SMP. A full memory barrier can be produced by ++// writing a random value to a very specific coprocessor register. ++// ++// * On ARMv7, the "dmb" instruction is used to perform a full memory ++// barrier (though writing to the co-processor will still work). ++// However, on single core devices (e.g. Nexus One, or Nexus S), ++// this instruction will take up to 200 ns, which is huge, even though ++// it's completely un-needed on these devices. ++// ++// * There is no easy way to determine at runtime if the device is ++// single or multi-core. However, the kernel provides a useful helper ++// function at a fixed memory address (0xffff0fa0), which will always ++// perform a memory barrier in the most efficient way. I.e. on single ++// core devices, this is an empty function that exits immediately. ++// On multi-core devices, it implements a full memory barrier. ++// ++// * This source could be compiled to ARMv5 machine code that runs on a ++// multi-core ARMv6 or ARMv7 device. In this case, memory barriers ++// are needed for correct execution. Always call the kernel helper, even ++// when targeting ARMv5TE. ++// + +-typedef void (*LinuxKernelMemoryBarrierFunc)(void); +-LinuxKernelMemoryBarrierFunc pLinuxKernelMemoryBarrier __attribute__((weak)) = +- (LinuxKernelMemoryBarrierFunc) 0xffff0fa0; ++inline void MemoryBarrier() { ++#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ ++ defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) ++ __asm__ __volatile__("dmb ish" ::: "memory"); ++#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ ++ defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \ ++ defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ++ __asm__ __volatile__("mcr p15,0,r0,c7,c10,5" ::: "memory"); ++#elif defined(__linux__) || defined(__ANDROID__) ++ // Note: This is a function call, which is also an implicit compiler barrier. ++ typedef void (*KernelMemoryBarrierFunc)(); ++ ((KernelMemoryBarrierFunc)0xffff0fa0)(); ++#error MemoryBarrier() is not implemented on this platform. ++#endif ++} + ++// An ARM toolchain would only define one of these depending on which ++// variant of the target architecture is being used. This tests against ++// any known ARMv6 or ARMv7 variant, where it is possible to directly ++// use ldrex/strex instructions to implement fast atomic operations. ++#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ ++ defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \ ++ defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ ++ defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \ ++ defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) + + inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { +- Atomic32 prev_value = *ptr; ++ Atomic32 prev_value; ++ int reloop; + do { +- if (!pLinuxKernelCmpxchg(old_value, new_value, +- const_cast<Atomic32*>(ptr))) { +- return old_value; +- } +- prev_value = *ptr; +- } while (prev_value == old_value); ++ // The following is equivalent to: ++ // ++ // prev_value = LDREX(ptr) ++ // reloop = 0 ++ // if (prev_value != old_value) ++ // reloop = STREX(ptr, new_value) ++ __asm__ __volatile__(" ldrex %0, [%3]\n" ++ " mov %1, #0\n" ++ " cmp %0, %4\n" ++#ifdef __thumb2__ ++ " it eq\n" ++#endif ++ " strexeq %1, %5, [%3]\n" ++ : "=&r"(prev_value), "=&r"(reloop), "+m"(*ptr) ++ : "r"(ptr), "r"(old_value), "r"(new_value) ++ : "cc", "memory"); ++ } while (reloop != 0); + return prev_value; + } + ++inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, ++ Atomic32 old_value, ++ Atomic32 new_value) { ++ Atomic32 result = NoBarrier_CompareAndSwap(ptr, old_value, new_value); ++ MemoryBarrier(); ++ return result; ++} ++ ++inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, ++ Atomic32 old_value, ++ Atomic32 new_value) { ++ MemoryBarrier(); ++ return NoBarrier_CompareAndSwap(ptr, old_value, new_value); ++} ++ ++inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, ++ Atomic32 increment) { ++ Atomic32 value; ++ int reloop; ++ do { ++ // Equivalent to: ++ // ++ // value = LDREX(ptr) ++ // value += increment ++ // reloop = STREX(ptr, value) ++ // ++ __asm__ __volatile__(" ldrex %0, [%3]\n" ++ " add %0, %0, %4\n" ++ " strex %1, %0, [%3]\n" ++ : "=&r"(value), "=&r"(reloop), "+m"(*ptr) ++ : "r"(ptr), "r"(increment) ++ : "cc", "memory"); ++ } while (reloop); ++ return value; ++} ++ ++inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, ++ Atomic32 increment) { ++ // TODO(digit): Investigate if it's possible to implement this with ++ // a single MemoryBarrier() operation between the LDREX and STREX. ++ // See http://crbug.com/246514 ++ MemoryBarrier(); ++ Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment); ++ MemoryBarrier(); ++ return result; ++} ++ + inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, + Atomic32 new_value) { + Atomic32 old_value; ++ int reloop; + do { ++ // old_value = LDREX(ptr) ++ // reloop = STREX(ptr, new_value) ++ __asm__ __volatile__(" ldrex %0, [%3]\n" ++ " strex %1, %4, [%3]\n" ++ : "=&r"(old_value), "=&r"(reloop), "+m"(*ptr) ++ : "r"(ptr), "r"(new_value) ++ : "cc", "memory"); ++ } while (reloop != 0); ++ return old_value; ++} ++ ++// This tests against any known ARMv5 variant. ++#elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \ ++ defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) ++ ++// The kernel also provides a helper function to perform an atomic ++// compare-and-swap operation at the hard-wired address 0xffff0fc0. ++// On ARMv5, this is implemented by a special code path that the kernel ++// detects and treats specially when thread pre-emption happens. ++// On ARMv6 and higher, it uses LDREX/STREX instructions instead. ++// ++// Note that this always perform a full memory barrier, there is no ++// need to add calls MemoryBarrier() before or after it. It also ++// returns 0 on success, and 1 on exit. ++// ++// Available and reliable since Linux 2.6.24. Both Android and ChromeOS ++// use newer kernel revisions, so this should not be a concern. ++namespace { ++ ++inline int LinuxKernelCmpxchg(Atomic32 old_value, ++ Atomic32 new_value, ++ volatile Atomic32* ptr) { ++ typedef int (*KernelCmpxchgFunc)(Atomic32, Atomic32, volatile Atomic32*); ++ return ((KernelCmpxchgFunc)0xffff0fc0)(old_value, new_value, ptr); ++} ++ ++} // namespace ++ ++inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, ++ Atomic32 old_value, ++ Atomic32 new_value) { ++ Atomic32 prev_value; ++ for (;;) { ++ prev_value = *ptr; ++ if (prev_value != old_value) ++ return prev_value; ++ if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) ++ return old_value; ++ } ++} ++ ++inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, ++ Atomic32 new_value) { ++ Atomic32 old_value; ++ do { + old_value = *ptr; +- } while (pLinuxKernelCmpxchg(old_value, new_value, +- const_cast<Atomic32*>(ptr))); ++ } while (LinuxKernelCmpxchg(old_value, new_value, ptr)); + return old_value; + } + +@@ -63,36 +237,57 @@ + // Atomic exchange the old value with an incremented one. + Atomic32 old_value = *ptr; + Atomic32 new_value = old_value + increment; +- if (pLinuxKernelCmpxchg(old_value, new_value, +- const_cast<Atomic32*>(ptr)) == 0) { ++ if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) { + // The exchange took place as expected. + return new_value; + } + // Otherwise, *ptr changed mid-loop and we need to retry. + } +- + } + + inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { +- return NoBarrier_CompareAndSwap(ptr, old_value, new_value); ++ Atomic32 prev_value; ++ for (;;) { ++ prev_value = *ptr; ++ if (prev_value != old_value) { ++ // Always ensure acquire semantics. ++ MemoryBarrier(); ++ return prev_value; ++ } ++ if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) ++ return old_value; ++ } + } + + inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, + Atomic32 old_value, + Atomic32 new_value) { +- return NoBarrier_CompareAndSwap(ptr, old_value, new_value); ++ // This could be implemented as: ++ // MemoryBarrier(); ++ // return NoBarrier_CompareAndSwap(); ++ // ++ // But would use 3 barriers per succesful CAS. To save performance, ++ // use Acquire_CompareAndSwap(). Its implementation guarantees that: ++ // - A succesful swap uses only 2 barriers (in the kernel helper). ++ // - An early return due to (prev_value != old_value) performs ++ // a memory barrier with no store, which is equivalent to the ++ // generic implementation above. ++ return Acquire_CompareAndSwap(ptr, old_value, new_value); + } + ++#else ++# error "Your CPU's ARM architecture is not supported yet" ++#endif ++ ++// NOTE: Atomicity of the following load and store operations is only ++// guaranteed in case of 32-bit alignement of |ptr| values. ++ + inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + } + +-inline void MemoryBarrier() { +- pLinuxKernelMemoryBarrier(); +-} +- + inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { + *ptr = value; + MemoryBarrier(); +@@ -103,9 +298,7 @@ + *ptr = value; + } + +-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { +- return *ptr; +-} ++inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { return *ptr; } + + inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { + Atomic32 value = *ptr; +@@ -118,7 +311,6 @@ + return *ptr; + } + +-} // namespace base::subtle +-} // namespace base ++} } // namespace base::subtle + + #endif // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_ |