summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
authoravi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-27 21:50:37 +0000
committeravi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-27 21:50:37 +0000
commit439f1c99d74bc572952b0e01ba30ee13681959b0 (patch)
treec3dff2918556c5986f4de06698b3082926f17744 /content/browser
parent38ba7ae8f8aa0a2399e466c36d458a9e38e94297 (diff)
downloadchromium_src-439f1c99d74bc572952b0e01ba30ee13681959b0.zip
chromium_src-439f1c99d74bc572952b0e01ba30ee13681959b0.tar.gz
chromium_src-439f1c99d74bc572952b0e01ba30ee13681959b0.tar.bz2
Move Leopard compatible block code to content/.
BUG=95573 TEST=no change Review URL: http://codereview.chromium.org/8060022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@103017 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/mac/closure_blocks_leopard_compat.S139
-rw-r--r--content/browser/mac/closure_blocks_leopard_compat.h104
-rw-r--r--content/browser/mac/closure_blocks_leopard_compat_unittest.cc98
3 files changed, 341 insertions, 0 deletions
diff --git a/content/browser/mac/closure_blocks_leopard_compat.S b/content/browser/mac/closure_blocks_leopard_compat.S
new file mode 100644
index 0000000..88a63da
--- /dev/null
+++ b/content/browser/mac/closure_blocks_leopard_compat.S
@@ -0,0 +1,139 @@
+# Copyright (c) 2011 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.
+
+# Definitions of symbols that may be needed at runtime but aren't necessarily
+# present in the SDK chosen for compilation.
+#
+# This file provides symbols for _NSConcreteGlobalBlock and
+# _NSConcreteStackBlock, normally present in libSystem.dylib and provided by
+# by libclosure-38/data.c in Mac OS X 10.6 and later. It also provides symbols
+# for various block runtime functions provided by libclosure-38/runtime.c.
+# When using the 10.5 SDK, the symbols are not present. This file's definition
+# can be used with extreme care in an application that needs to use the 10.5
+# SDK in conjunction with blocks.
+#
+# This file cooperates with the build system to produce a dynamic library
+# that, when linked against, causes dependents to look in libSystem for the
+# symbols provided here. It also cooperates with a header that causes
+# dependents to treat the symbols provided here as weak imports, critical for
+# the resultant output to be loadable on 10.5.
+
+# To simplify things, this file assumes it's being built with the 10.5 SDK,
+# a deployment target of 10.5, and is producing 32-bit x86 code. Other
+# combinations are possible, but not interesting for the time being. See
+# <sys/cdefs.h> for interesting ways that names might be mangled in other
+# configurations.
+
+#include <AvailabilityMacros.h>
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED != MAC_OS_X_VERSION_10_5 || \
+ MAC_OS_X_VERSION_MAX_ALLOWED != MAC_OS_X_VERSION_10_5 || \
+ !defined(__i386__)
+#error This file only supports 32-bit x86 code with both SDK and DT set to 10.5
+#endif
+
+#define DEFINE_GLOBAL_SYMBOL(name) \
+ .globl name ## ;\
+ name ## :
+
+.text
+
+# Mac OS X 10.6.8 libclosure-38/runtime.c
+
+DEFINE_GLOBAL_SYMBOL(__Block_copy)
+DEFINE_GLOBAL_SYMBOL(__Block_release)
+DEFINE_GLOBAL_SYMBOL(__Block_object_assign)
+DEFINE_GLOBAL_SYMBOL(__Block_object_dispose)
+
+.section __DATA,__data
+
+# Mac OS X 10.6.8 libclosure-38/data.c
+
+DEFINE_GLOBAL_SYMBOL(__NSConcreteGlobalBlock)
+DEFINE_GLOBAL_SYMBOL(__NSConcreteStackBlock)
+
+# When this file is in use, the linker is expected to link things against both
+# this file and the real copy of libSystem present in the SDK. When doing so,
+# the linker is smart enough to produce only one LC_LOAD_DYLIB load command.
+# However, it's not smart enough to notice that while this file's dylib only
+# provides weak-imported symbols, the real libSystem's dylib does not.
+# Consequently, it may produce an LC_LOAD_WEAK_DYLIB load command for
+# libSystem instead of an ordinary LC_LOAD_DYLIB command. LC_LOAD_WEAK_DYLIB
+# declares that any symbol offered by the library, and in fact the entire
+# library, is permitted to be missing at runtime. This is entirely
+# inappropriate for libSystem. To counteract this problem, this file also
+# defines some other symbols that libSystem provides. Dependents of this
+# library are not expected to treat these other symbols as weak imports. In
+# order for any dependent that links against this library to load it with an
+# LC_LOAD_DYLIB command instead of an LC_LOAD_WEAK_DYLIB command, this library
+# must satisfy at least one unresolved non-weak-import symbol required by the
+# dependent.
+
+.text
+
+# |exit| is a good one: because it's referenced by crt1.o, ordinary executables
+# are guaranteed to need this symbol. Unfortunately, there's no such symbol in
+# dylib1.o that libSystem is expected to provide, so a few other common libc
+# symbols are thrown into the mix.
+DEFINE_GLOBAL_SYMBOL(_exit)
+
+# Include |close| because well-written programs that use the standard library
+# are likely to refer to it. Include |open| for good measure because it goes
+# pretty well with this. Include the stdio abstractions for these functions
+# as well.
+DEFINE_GLOBAL_SYMBOL(_close$UNIX2003)
+DEFINE_GLOBAL_SYMBOL(_open$UNIX2003)
+DEFINE_GLOBAL_SYMBOL(_fclose)
+DEFINE_GLOBAL_SYMBOL(_fopen)
+DEFINE_GLOBAL_SYMBOL(_fdopen)
+DEFINE_GLOBAL_SYMBOL(_freopen$UNIX2003)
+
+# Commonly-used allocation functions.
+DEFINE_GLOBAL_SYMBOL(_malloc)
+DEFINE_GLOBAL_SYMBOL(_calloc)
+DEFINE_GLOBAL_SYMBOL(_realloc)
+DEFINE_GLOBAL_SYMBOL(_reallocf)
+DEFINE_GLOBAL_SYMBOL(_valloc)
+DEFINE_GLOBAL_SYMBOL(_free)
+
+# Include |printf|, |fprintf|, |sprintf|, |snprintf|, and |puts|, because
+# small test programs are likely to refer to one of these. puts is rarely
+# invoked directly, but the compiler may optimize simple printf calls into
+# puts calls.
+DEFINE_GLOBAL_SYMBOL(_printf)
+DEFINE_GLOBAL_SYMBOL(_fprintf)
+DEFINE_GLOBAL_SYMBOL(_sprintf)
+DEFINE_GLOBAL_SYMBOL(_snprintf)
+DEFINE_GLOBAL_SYMBOL(_puts)
+
+# Some <string.h> functions that are commonly used.
+DEFINE_GLOBAL_SYMBOL(_memcmp)
+DEFINE_GLOBAL_SYMBOL(_memcpy)
+DEFINE_GLOBAL_SYMBOL(_memmove)
+DEFINE_GLOBAL_SYMBOL(_memset)
+DEFINE_GLOBAL_SYMBOL(_strcasecmp)
+DEFINE_GLOBAL_SYMBOL(_strcat)
+DEFINE_GLOBAL_SYMBOL(_strchr)
+DEFINE_GLOBAL_SYMBOL(_strcmp)
+DEFINE_GLOBAL_SYMBOL(_strcpy)
+DEFINE_GLOBAL_SYMBOL(_strdup)
+DEFINE_GLOBAL_SYMBOL(_strlcat)
+DEFINE_GLOBAL_SYMBOL(_strlcpy)
+DEFINE_GLOBAL_SYMBOL(_strlen)
+DEFINE_GLOBAL_SYMBOL(_strncasecmp)
+DEFINE_GLOBAL_SYMBOL(_strncat)
+DEFINE_GLOBAL_SYMBOL(_strncmp)
+DEFINE_GLOBAL_SYMBOL(_strncpy)
+DEFINE_GLOBAL_SYMBOL(_strnstr)
+DEFINE_GLOBAL_SYMBOL(_strstr)
+
+# Some data-section symbols that might be referenced.
+
+.section __DATA,__data
+
+DEFINE_GLOBAL_SYMBOL(___stdinp)
+DEFINE_GLOBAL_SYMBOL(___stdoutp)
+DEFINE_GLOBAL_SYMBOL(___stderrp)
+
+#undef DEFINE_GLOBAL_SYMBOL
diff --git a/content/browser/mac/closure_blocks_leopard_compat.h b/content/browser/mac/closure_blocks_leopard_compat.h
new file mode 100644
index 0000000..518c7b1
--- /dev/null
+++ b/content/browser/mac/closure_blocks_leopard_compat.h
@@ -0,0 +1,104 @@
+// Copyright (c) 2011 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.
+
+#ifndef CONTENT_BROWSER_MAC_CLOSURE_BLOCKS_LEOPARD_COMPAT_H_
+#define CONTENT_BROWSER_MAC_CLOSURE_BLOCKS_LEOPARD_COMPAT_H_
+#pragma once
+
+// libclosure (blocks) compatibility for Mac OS X 10.5 (Leopard)
+//
+// Background material:
+// http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Blocks
+// http://opensource.apple.com/source/libclosure/libclosure-38/
+//
+// Leopard doesn't support blocks. Chrome supports Leopard. Chrome needs to use
+// blocks.
+//
+// In any file where you use blocks (any time you type ^{...}), you must
+// #include this file to ensure that the runtime symbols referenced by code
+// emitted by the compiler are marked for weak-import. This means that if
+// these symbols are not present at runtime, the program will still load, but
+// their values will be NULL.
+//
+// In any target (in the GYP sense) where you use blocks, you must also depend
+// on the closure_blocks_leopard_compat target to ensure that these symbols
+// will be available at link time, even when the 10.5 SDK is in use. This
+// allows the continued use of the 10.5 SDK, which does not contain these
+// symbols.
+//
+// This does not relieve you of the responsibility to not use blocks on
+// Leopard. Because runtime support for Blocks still isn't present on that
+// operating system, the weak-imported symbols will have value 0 and attempts
+// to do anything meaningful with them will fail or crash. You must take care
+// not to enter any codepath that uses blocks on Leopard. The base::mac::IsOS*
+// family may be helpful.
+//
+// Although this scheme allows the use of the 10.5 SDK and 10.5 runtime in an
+// application that uses blocks, it is still necessary to use a compiler that
+// supports blocks. GCC 4.2 as shipped with Xcode 3.2 for Mac OS X 10.6
+// qualifies, as do sufficiently recent versions of clang. GCC 4.2 as shipped
+// with Xcode 3.1 for Mac OS X 10.5 does not qualify.
+
+// _NSConcreteGlobalBlock and _NSConcreteStackBlock are private implementation
+// details of libclosure defined in libclosure/libclosure-38/Block_private.h,
+// but they're exposed from libSystem as public symbols, and the block-enabled
+// compiler will emit code that references these symbols. Because the symbols
+// aren't present in 10.5's libSystem, they must be declared as weak imports
+// in any file that uses blocks. Any block-using file must #include this
+// header to guarantee that the symbols will show up in linked output as weak
+// imports when compiling for a 10.5 deployment target. Because the symbols
+// are always present in 10.6 and higher, they do not need to be a weak
+// imports when the deployment target is at least 10.6.
+//
+// Both GCC and clang emit references to these symbols, providing implicit
+// declarations as needed, but respecting any user declaration when present.
+// See gcc-5666.3/gcc/c-parser.c build_block_struct_initlist,
+// gcc-5666.3/gcc/cp/parser.c build_block_struct_initlist, and
+// clang-2.9/lib/CodeGen/CodeGenModule.cpp
+// CodeGenModule::getNSConcreteGlobalBlock() and
+// CodeGenModule::getNSConcreteStackBlock().
+
+#include <AvailabilityMacros.h>
+
+#if defined(MAC_OS_X_VERSION_10_6) && \
+ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 // SDK >= 10.6
+// Get the system's own declarations of these things if using an SDK where
+// they are present.
+#include <Block.h>
+#endif // SDK >= 10.6
+
+extern "C" {
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 // DT <= 10.5
+#define MAYBE_WEAK_IMPORT __attribute__((weak_import))
+#else // DT > 10.5
+#define MAYBE_WEAK_IMPORT
+#endif // DT <= 10.5
+
+MAYBE_WEAK_IMPORT extern void* _Block_copy(const void*);
+MAYBE_WEAK_IMPORT extern void _Block_release(const void*);
+MAYBE_WEAK_IMPORT extern void _Block_object_assign(void*,
+ const void*,
+ const int);
+MAYBE_WEAK_IMPORT extern void _Block_object_dispose(const void*, const int);
+
+MAYBE_WEAK_IMPORT extern void* _NSConcreteGlobalBlock[32];
+MAYBE_WEAK_IMPORT extern void* _NSConcreteStackBlock[32];
+
+#undef MAYBE_WEAK_IMPORT
+
+} // extern "C"
+
+// Macros from <Block.h>, in case <Block.h> is not present.
+
+#ifndef Block_copy
+#define Block_copy(...) \
+ ((__typeof(__VA_ARGS__))_Block_copy((const void *)(__VA_ARGS__)))
+#endif
+
+#ifndef Block_release
+#define Block_release(...) _Block_release((const void *)(__VA_ARGS__))
+#endif
+
+#endif // CONTENT_BROWSER_MAC_CLOSURE_BLOCKS_LEOPARD_COMPAT_H_
diff --git a/content/browser/mac/closure_blocks_leopard_compat_unittest.cc b/content/browser/mac/closure_blocks_leopard_compat_unittest.cc
new file mode 100644
index 0000000..fd2e467
--- /dev/null
+++ b/content/browser/mac/closure_blocks_leopard_compat_unittest.cc
@@ -0,0 +1,98 @@
+// Copyright (c) 2011 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.
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "base/mac/mac_util.h"
+#include "content/browser/mac/closure_blocks_leopard_compat.h"
+
+// Used in ClosureBlocksLeopardCompatTest.Global. Putting a block at global
+// scope results in a block structure whose isa field is set to
+// NSConcreteGlobalBlock, ensuring that symbol is referenced. This test needs
+// to be able to load on 10.5 where that symbol is not present at runtime, so
+// the real test here is that the symbol is weakly imported. If not, the
+// executable will fail to load.
+void (^global_block)(bool*) = ^(bool* ran_pointer) { *ran_pointer = true; };
+
+namespace {
+
+// It should be possible to declare a block on OSes as early as Leopard
+// (10.5). This should be buildable with the 10.5 SDK and a 10.5 deployment
+// target, and runnable on 10.5. However, the block itself is not expected to
+// be runnable on 10.5. This test verfies that blocks are buildable on 10.5
+// and runnable on Snow Leopard (10.6) and later.
+
+TEST(ClosureBlocksLeopardCompatTest, Stack) {
+ bool ran = false;
+
+ // This should result in a block structure whose isa field is set to
+ // NSConcreteStackBlock, ensuring that symbol is referenced. This test
+ // needs to be able to load on 10.5 where that symbol is not present at
+ // runtime, so the real test here checks that the symbol is weakly imported.
+ // If not, the executable will fail to load.
+
+ void (^test_block)(bool*) = ^(bool* ran_pointer) { *ran_pointer = true; };
+
+ ASSERT_FALSE(ran);
+
+ if (base::mac::IsOSSnowLeopardOrLater()) {
+ test_block(&ran);
+
+ EXPECT_TRUE(ran);
+ }
+}
+
+TEST(ClosureBlocksLeopardCompatTest, Global) {
+ bool ran = false;
+
+ ASSERT_FALSE(ran);
+
+ if (base::mac::IsOSSnowLeopardOrLater()) {
+ global_block(&ran);
+
+ EXPECT_TRUE(ran);
+ }
+}
+
+TEST(ClosureBlocksLeopardCompatTest, CopyRelease) {
+ if (base::mac::IsOSSnowLeopardOrLater()) {
+ // Protect the entire test in this conditional, because __block won't run
+ // on 10.5.
+ __block int value = 0;
+
+ typedef int (^TestBlockType)();
+ TestBlockType local_block = ^(void) { return ++value; };
+
+ ASSERT_EQ(0, value);
+
+ int rv = local_block();
+ EXPECT_EQ(1, rv);
+ EXPECT_EQ(rv, value);
+
+ // Using Block_copy, Block_release, and these other operations ensures
+ // that _Block_copy, _Block_release, _Block_object_assign, and
+ // _Block_object_dispose are referenced. This test needs to be able to
+ // load on 10.5 where these symbols are not present at runtime, so the
+ // real test here is that the symbol is weakly imported. If not, the
+ // executable will fail to load.
+
+ TestBlockType copied_block = Block_copy(local_block);
+
+ rv = copied_block();
+ EXPECT_EQ(2, rv);
+ EXPECT_EQ(rv, value);
+
+ rv = copied_block();
+ EXPECT_EQ(3, rv);
+ EXPECT_EQ(rv, value);
+
+ Block_release(copied_block);
+
+ rv = local_block();
+ EXPECT_EQ(4, rv);
+ EXPECT_EQ(rv, value);
+ }
+}
+
+} // namespace